mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-03-16 07:30:51 +00:00
refactor: async routing (#489)
* feat: async routing * chore: put dht extra api commands under content routing * chore: add default option to createPeerInfo Co-Authored-By: Jacob Heun <jacobheun@gmail.com> * chore: address review * chore: rm dlv
This commit is contained in:
parent
f77ce39484
commit
a020db183a
@ -43,6 +43,7 @@
|
||||
"dependencies": {
|
||||
"abort-controller": "^3.0.0",
|
||||
"async": "^2.6.2",
|
||||
"async-iterator-all": "^1.0.0",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"debug": "^4.1.1",
|
||||
@ -62,6 +63,7 @@
|
||||
"multiaddr": "^7.2.1",
|
||||
"multistream-select": "^0.15.0",
|
||||
"once": "^1.4.0",
|
||||
"p-any": "^2.1.0",
|
||||
"p-map": "^3.0.0",
|
||||
"p-queue": "^6.1.1",
|
||||
"p-settle": "^3.1.0",
|
||||
@ -90,11 +92,11 @@
|
||||
"interface-datastore": "^0.6.0",
|
||||
"it-pair": "^1.0.0",
|
||||
"libp2p-bootstrap": "^0.10.3",
|
||||
"libp2p-delegated-content-routing": "^0.2.2",
|
||||
"libp2p-delegated-peer-routing": "^0.2.2",
|
||||
"libp2p-delegated-content-routing": "^0.4.1",
|
||||
"libp2p-delegated-peer-routing": "^0.4.0",
|
||||
"libp2p-floodsub": "^0.19.0",
|
||||
"libp2p-gossipsub": "^0.1.0",
|
||||
"libp2p-kad-dht": "~0.17.0",
|
||||
"libp2p-kad-dht": "^0.18.0",
|
||||
"libp2p-mdns": "^0.13.0",
|
||||
"libp2p-mplex": "^0.9.1",
|
||||
"libp2p-pnet": "~0.1.0",
|
||||
@ -105,6 +107,7 @@
|
||||
"lodash.times": "^4.3.2",
|
||||
"nock": "^10.0.6",
|
||||
"p-defer": "^3.0.0",
|
||||
"p-times": "^2.1.0",
|
||||
"p-wait-for": "^3.1.0",
|
||||
"portfinder": "^1.0.20",
|
||||
"pull-goodbye": "0.0.2",
|
||||
|
@ -1,16 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
const tryEach = require('async/tryEach')
|
||||
const parallel = require('async/parallel')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
const { messages, codes } = require('./errors')
|
||||
|
||||
const all = require('async-iterator-all')
|
||||
const pAny = require('p-any')
|
||||
|
||||
module.exports = (node) => {
|
||||
const routers = node._modules.contentRouting || []
|
||||
const dht = node._dht
|
||||
|
||||
// If we have the dht, make it first
|
||||
if (node._dht) {
|
||||
routers.unshift(node._dht)
|
||||
if (dht) {
|
||||
routers.unshift(dht)
|
||||
}
|
||||
|
||||
return {
|
||||
@ -19,66 +21,93 @@ module.exports = (node) => {
|
||||
* Once a content router succeeds, iteration will stop.
|
||||
*
|
||||
* @param {CID} key The CID key of the content to find
|
||||
* @param {object} options
|
||||
* @param {number} options.maxTimeout How long the query should run
|
||||
* @param {number} options.maxNumProviders - maximum number of providers to find
|
||||
* @param {function(Error, Result<Array>)} callback
|
||||
* @returns {void}
|
||||
* @param {object} [options]
|
||||
* @param {number} [options.timeout] How long the query should run
|
||||
* @param {number} [options.maxNumProviders] - maximum number of providers to find
|
||||
* @returns {AsyncIterable<PeerInfo>}
|
||||
*/
|
||||
findProviders: promisify((key, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
} else if (typeof options === 'number') { // This can be deprecated in a future release
|
||||
options = {
|
||||
maxTimeout: options
|
||||
}
|
||||
}
|
||||
|
||||
async * findProviders (key, options) {
|
||||
if (!routers.length) {
|
||||
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||
}
|
||||
|
||||
const tasks = routers.map((router) => {
|
||||
return (cb) => router.findProviders(key, options, (err, results) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
const result = await pAny(
|
||||
routers.map(async (router) => {
|
||||
const provs = await all(router.findProviders(key, options))
|
||||
|
||||
// If we don't have any results, we need to provide an error to keep trying
|
||||
if (!results || Object.keys(results).length === 0) {
|
||||
return cb(errCode(new Error('not found'), 'NOT_FOUND'), null)
|
||||
if (!provs || !provs.length) {
|
||||
throw errCode(new Error('not found'), 'NOT_FOUND')
|
||||
}
|
||||
|
||||
cb(null, results)
|
||||
return provs
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
tryEach(tasks, (err, results) => {
|
||||
if (err && err.code !== 'NOT_FOUND') {
|
||||
return callback(err)
|
||||
}
|
||||
results = results || []
|
||||
callback(null, results)
|
||||
})
|
||||
}),
|
||||
for (const pInfo of result) {
|
||||
yield pInfo
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterates over all content routers in parallel to notify it is
|
||||
* a provider of the given key.
|
||||
*
|
||||
* @param {CID} key The CID key of the content to find
|
||||
* @param {function(Error)} callback
|
||||
* @returns {void}
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
provide: promisify((key, callback) => {
|
||||
async provide (key) { // eslint-disable-line require-await
|
||||
if (!routers.length) {
|
||||
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||
}
|
||||
|
||||
parallel(routers.map((router) => {
|
||||
return (cb) => router.provide(key, cb)
|
||||
}), callback)
|
||||
})
|
||||
return Promise.all(routers.map((router) => router.provide(key)))
|
||||
},
|
||||
|
||||
/**
|
||||
* Store the given key/value pair in the DHT.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} value
|
||||
* @param {Object} [options] - put options
|
||||
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async put (key, value, options) { // eslint-disable-line require-await
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.put(key, value, options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the value to the given key.
|
||||
* Times out after 1 minute by default.
|
||||
* @param {Buffer} key
|
||||
* @param {Object} [options] - get options
|
||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||
* @returns {Promise<{from: PeerId, val: Buffer}>}
|
||||
*/
|
||||
async get (key, options) { // eslint-disable-line require-await
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.get(key, options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the `n` values to the given key without sorting.
|
||||
* @param {Buffer} key
|
||||
* @param {number} nVals
|
||||
* @param {Object} [options] - get options
|
||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||
* @returns {Promise<Array<{from: PeerId, val: Buffer}>>}
|
||||
*/
|
||||
async getMany (key, nVals, options) { // eslint-disable-line require-await
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.getMany(key, nVals, options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
72
src/dht.js
72
src/dht.js
@ -1,72 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const errCode = require('err-code')
|
||||
|
||||
const { messages, codes } = require('./errors')
|
||||
|
||||
module.exports = (node, DHT, config) => {
|
||||
const dht = new DHT({
|
||||
dialer: node.dialer,
|
||||
peerInfo: node.peerInfo,
|
||||
peerStore: node.peerStore,
|
||||
registrar: node.registrar,
|
||||
datastore: this.datastore,
|
||||
...config
|
||||
})
|
||||
|
||||
return {
|
||||
/**
|
||||
* Store the given key/value pair in the DHT.
|
||||
* @param {Buffer} key
|
||||
* @param {Buffer} value
|
||||
* @param {Object} [options] - put options
|
||||
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
put: (key, value, options) => {
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.put(key, value, options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the value to the given key.
|
||||
* Times out after 1 minute by default.
|
||||
* @param {Buffer} key
|
||||
* @param {Object} [options] - get options
|
||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||
* @returns {Promise<{from: PeerId, val: Buffer}>}
|
||||
*/
|
||||
get: (key, options) => {
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.get(key, options)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the `n` values to the given key without sorting.
|
||||
* @param {Buffer} key
|
||||
* @param {number} nVals
|
||||
* @param {Object} [options] - get options
|
||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||
* @returns {Promise<Array<{from: PeerId, val: Buffer}>>}
|
||||
*/
|
||||
getMany: (key, nVals, options) => {
|
||||
if (!node.isStarted() || !dht.isStarted) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||
}
|
||||
|
||||
return dht.getMany(key, nVals, options)
|
||||
},
|
||||
|
||||
_dht: dht,
|
||||
|
||||
start: () => dht.start(),
|
||||
|
||||
stop: () => dht.stop()
|
||||
}
|
||||
}
|
13
src/index.js
13
src/index.js
@ -10,7 +10,6 @@ const multiaddr = require('multiaddr')
|
||||
|
||||
const peerRouting = require('./peer-routing')
|
||||
const contentRouting = require('./content-routing')
|
||||
const dht = require('./dht')
|
||||
const pubsub = require('./pubsub')
|
||||
const { getPeerInfo, getPeerInfoRemote } = require('./get-peer-info')
|
||||
const { validate: validateConfig } = require('./config')
|
||||
@ -124,7 +123,15 @@ class Libp2p extends EventEmitter {
|
||||
|
||||
// dht provided components (peerRouting, contentRouting, dht)
|
||||
if (this._modules.dht) {
|
||||
this._dht = dht(this, this._modules.dht, this._config.dht)
|
||||
const DHT = this._modules.dht
|
||||
this._dht = new DHT({
|
||||
dialer: this.dialer,
|
||||
peerInfo: this.peerInfo,
|
||||
peerStore: this.peerStore,
|
||||
registrar: this.registrar,
|
||||
datastore: this.datastore,
|
||||
...this._config.dht
|
||||
})
|
||||
}
|
||||
|
||||
// start pubsub
|
||||
@ -333,7 +340,7 @@ class Libp2p extends EventEmitter {
|
||||
|
||||
// TODO: this should be modified once random-walk is used as
|
||||
// the other discovery modules
|
||||
this._dht._dht.on('peer', this._peerDiscovered)
|
||||
this._dht.on('peer', this._peerDiscovered)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const tryEach = require('async/tryEach')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
const pAny = require('p-any')
|
||||
|
||||
module.exports = (node) => {
|
||||
const routers = node._modules.peerRouting || []
|
||||
@ -17,43 +16,25 @@ module.exports = (node) => {
|
||||
* Iterates over all peer routers in series to find the given peer.
|
||||
*
|
||||
* @param {String} id The id of the peer to find
|
||||
* @param {object} options
|
||||
* @param {number} options.maxTimeout How long the query should run
|
||||
* @param {function(Error, Result<Array>)} callback
|
||||
* @returns {void}
|
||||
* @param {object} [options]
|
||||
* @param {number} [options.timeout] How long the query should run
|
||||
* @returns {Promise<PeerInfo>}
|
||||
*/
|
||||
findPeer: promisify((id, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
findPeer: async (id, options) => { // eslint-disable-line require-await
|
||||
if (!routers.length) {
|
||||
callback(errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||
}
|
||||
|
||||
const tasks = routers.map((router) => {
|
||||
return (cb) => router.findPeer(id, options, (err, result) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
return pAny(routers.map(async (router) => {
|
||||
const result = await router.findPeer(id, options)
|
||||
|
||||
// If we don't have a result, we need to provide an error to keep trying
|
||||
if (!result || Object.keys(result).length === 0) {
|
||||
return cb(errCode(new Error('not found'), 'NOT_FOUND'), null)
|
||||
}
|
||||
|
||||
cb(null, result)
|
||||
})
|
||||
})
|
||||
|
||||
tryEach(tasks, (err, results) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
// If we don't have a result, we need to provide an error to keep trying
|
||||
if (!result || Object.keys(result).length === 0) {
|
||||
throw errCode(new Error('not found'), 'NOT_FOUND')
|
||||
}
|
||||
results = results || []
|
||||
callback(null, results)
|
||||
})
|
||||
})
|
||||
|
||||
return result
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
323
test/content-routing/content-routing.node.js
Normal file
323
test/content-routing/content-routing.node.js
Normal file
@ -0,0 +1,323 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const chai = require('chai')
|
||||
chai.use(require('dirty-chai'))
|
||||
const { expect } = chai
|
||||
const nock = require('nock')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const pDefer = require('p-defer')
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const CID = require('cids')
|
||||
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
|
||||
const multiaddr = require('multiaddr')
|
||||
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
const { baseOptions, routingOptions } = require('./utils')
|
||||
|
||||
describe('content-routing', () => {
|
||||
describe('no routers', () => {
|
||||
let node
|
||||
|
||||
before(async () => {
|
||||
[node] = await peerUtils.createPeer({
|
||||
config: baseOptions
|
||||
})
|
||||
})
|
||||
|
||||
it('.findProviders should return an error', async () => {
|
||||
try {
|
||||
for await (const _ of node.contentRouting.findProviders('a cid')) {} // eslint-disable-line no-unused-vars
|
||||
throw new Error('.findProviders should return an error')
|
||||
} catch (err) {
|
||||
expect(err).to.exist()
|
||||
expect(err.code).to.equal('NO_ROUTERS_AVAILABLE')
|
||||
}
|
||||
})
|
||||
|
||||
it('.provide should return an error', async () => {
|
||||
await expect(node.contentRouting.provide('a cid'))
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'NO_ROUTERS_AVAILABLE')
|
||||
})
|
||||
})
|
||||
|
||||
describe('via dht router', () => {
|
||||
const number = 5
|
||||
let nodes
|
||||
|
||||
before(async () => {
|
||||
nodes = await peerUtils.createPeer({
|
||||
number,
|
||||
config: routingOptions
|
||||
})
|
||||
|
||||
// Ring dial
|
||||
await Promise.all(
|
||||
nodes.map((peer, i) => peer.dial(nodes[(i + 1) % number].peerInfo))
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
after(() => Promise.all(nodes.map((n) => n.stop())))
|
||||
|
||||
it('should use the nodes dht to provide', () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(nodes[0]._dht, 'provide').callsFake(() => {
|
||||
deferred.resolve()
|
||||
})
|
||||
|
||||
nodes[0].contentRouting.provide()
|
||||
return deferred.promise
|
||||
})
|
||||
|
||||
it('should use the nodes dht to find providers', async () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(nodes[0]._dht, 'findProviders').callsFake(function * () {
|
||||
deferred.resolve()
|
||||
yield
|
||||
})
|
||||
|
||||
await nodes[0].contentRouting.findProviders().next()
|
||||
|
||||
return deferred.promise
|
||||
})
|
||||
})
|
||||
|
||||
describe('via delegate router', () => {
|
||||
let node
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfo({ fixture: false })
|
||||
|
||||
delegate = new DelegatedContentRouter(peerInfo.id, {
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
}, [
|
||||
multiaddr('/ip4/0.0.0.0/tcp/60197')
|
||||
])
|
||||
|
||||
;[node] = await peerUtils.createPeer({
|
||||
config: mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
contentRouting: [delegate]
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
afterEach(() => node.stop())
|
||||
|
||||
it('should use the delegate router to provide', () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(delegate, 'provide').callsFake(() => {
|
||||
deferred.resolve()
|
||||
})
|
||||
|
||||
node.contentRouting.provide()
|
||||
return deferred.promise
|
||||
})
|
||||
|
||||
it('should use the delegate router to find providers', async () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(delegate, 'findProviders').callsFake(function * () {
|
||||
deferred.resolve()
|
||||
yield
|
||||
})
|
||||
|
||||
await node.contentRouting.findProviders().next()
|
||||
|
||||
return deferred.promise
|
||||
})
|
||||
|
||||
it('should be able to register as a provider', async () => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
// mock the refs call
|
||||
.post('/api/v0/refs')
|
||||
.query({
|
||||
recursive: false,
|
||||
arg: cid.toBaseEncodedString()
|
||||
})
|
||||
.reply(200, null, [
|
||||
'Content-Type', 'application/json',
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
|
||||
await node.contentRouting.provide(cid)
|
||||
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should handle errors when registering as a provider', async () => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
// mock the refs call
|
||||
.post('/api/v0/refs')
|
||||
.query({
|
||||
recursive: false,
|
||||
arg: cid.toBaseEncodedString()
|
||||
})
|
||||
.reply(502, 'Bad Gateway', ['Content-Type', 'application/json'])
|
||||
|
||||
await expect(node.contentRouting.provide(cid))
|
||||
.to.eventually.be.rejected()
|
||||
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should be able to find providers', async () => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const provider = 'QmZNgCqZCvTsi3B4Vt7gsSqpkqDpE7M2Y9TDmEhbDb4ceF'
|
||||
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
.post('/api/v0/dht/findprovs')
|
||||
.query({
|
||||
arg: cid.toBaseEncodedString()
|
||||
})
|
||||
.reply(200, `{"Extra":"","ID":"QmWKqWXCtRXEeCQTo3FoZ7g4AfnGiauYYiczvNxFCHicbB","Responses":[{"Addrs":["/ip4/0.0.0.0/tcp/0"],"ID":"${provider}"}],"Type":4}\n`, [
|
||||
'Content-Type', 'application/json',
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
|
||||
const providers = []
|
||||
for await (const provider of node.contentRouting.findProviders(cid, { timeout: 1000 })) {
|
||||
providers.push(provider)
|
||||
}
|
||||
|
||||
expect(providers).to.have.length(1)
|
||||
expect(providers[0].id.toB58String()).to.equal(provider)
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should handle errors when finding providers', async () => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
.post('/api/v0/dht/findprovs')
|
||||
.query({
|
||||
arg: cid.toBaseEncodedString()
|
||||
})
|
||||
.reply(502, 'Bad Gateway', [
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
|
||||
try {
|
||||
for await (const _ of node.contentRouting.findProviders(cid)) { } // eslint-disable-line no-unused-vars
|
||||
throw new Error('should handle errors when finding providers')
|
||||
} catch (err) {
|
||||
expect(err).to.exist()
|
||||
}
|
||||
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('via dht and delegate routers', () => {
|
||||
let node
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfo({ fixture: false })
|
||||
|
||||
delegate = new DelegatedContentRouter(peerInfo.id, {
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
}, [
|
||||
multiaddr('/ip4/0.0.0.0/tcp/60197')
|
||||
])
|
||||
|
||||
;[node] = await peerUtils.createPeer({
|
||||
config: mergeOptions(routingOptions, {
|
||||
modules: {
|
||||
contentRouting: [delegate]
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
afterEach(() => node.stop())
|
||||
|
||||
it('should use both the dht and delegate router to provide', async () => {
|
||||
const dhtDeferred = pDefer()
|
||||
const delegatedDeferred = pDefer()
|
||||
|
||||
sinon.stub(node._dht, 'provide').callsFake(() => {
|
||||
dhtDeferred.resolve()
|
||||
})
|
||||
|
||||
sinon.stub(delegate, 'provide').callsFake(() => {
|
||||
delegatedDeferred.resolve()
|
||||
})
|
||||
|
||||
await node.contentRouting.provide()
|
||||
|
||||
await Promise.all([
|
||||
dhtDeferred.promise,
|
||||
delegatedDeferred.promise
|
||||
])
|
||||
})
|
||||
|
||||
it('should only use the dht if it finds providers', async () => {
|
||||
const results = [true]
|
||||
|
||||
sinon.stub(node._dht, 'findProviders').callsFake(function * () {
|
||||
yield results[0]
|
||||
})
|
||||
|
||||
sinon.stub(delegate, 'findProviders').callsFake(function * () { // eslint-disable-line require-yield
|
||||
throw new Error('the delegate should not have been called')
|
||||
})
|
||||
|
||||
const providers = []
|
||||
for await (const prov of node.contentRouting.findProviders('a cid')) {
|
||||
providers.push(prov)
|
||||
}
|
||||
|
||||
expect(providers).to.have.length.above(0)
|
||||
expect(providers).to.eql(results)
|
||||
})
|
||||
|
||||
it('should use the delegate if the dht fails to find providers', async () => {
|
||||
const results = [true]
|
||||
|
||||
sinon.stub(node._dht, 'findProviders').callsFake(function * () {})
|
||||
|
||||
sinon.stub(delegate, 'findProviders').callsFake(function * () {
|
||||
yield results[0]
|
||||
})
|
||||
|
||||
const providers = []
|
||||
for await (const prov of node.contentRouting.findProviders('a cid')) {
|
||||
providers.push(prov)
|
||||
}
|
||||
|
||||
expect(providers).to.have.length.above(0)
|
||||
expect(providers).to.eql(results)
|
||||
})
|
||||
})
|
||||
})
|
@ -8,9 +8,9 @@ const { expect } = chai
|
||||
const mergeOptions = require('merge-options')
|
||||
const multiaddr = require('multiaddr')
|
||||
|
||||
const { create } = require('../../src')
|
||||
const { create } = require('../../../src')
|
||||
const { baseOptions, subsystemOptions } = require('./utils')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
const peerUtils = require('../../utils/creators/peer')
|
||||
|
||||
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
|
||||
@ -32,7 +32,7 @@ describe('DHT subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
it('should start and stop by default once libp2p starts', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
@ -40,17 +40,17 @@ describe('DHT subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(false)
|
||||
expect(libp2p._dht.isStarted).to.equal(false)
|
||||
|
||||
await libp2p.start()
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(true)
|
||||
expect(libp2p._dht.isStarted).to.equal(true)
|
||||
|
||||
await libp2p.stop()
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(false)
|
||||
expect(libp2p._dht.isStarted).to.equal(false)
|
||||
})
|
||||
|
||||
it('should not start if disabled once libp2p starts', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
@ -63,14 +63,14 @@ describe('DHT subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(false)
|
||||
expect(libp2p._dht.isStarted).to.equal(false)
|
||||
|
||||
await libp2p.start()
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(false)
|
||||
expect(libp2p._dht.isStarted).to.equal(false)
|
||||
})
|
||||
|
||||
it('should allow a manual start', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
@ -84,9 +84,9 @@ describe('DHT subsystem is configurable', () => {
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
await libp2p.start()
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(false)
|
||||
expect(libp2p._dht.isStarted).to.equal(false)
|
||||
|
||||
await libp2p._dht.start()
|
||||
expect(libp2p._dht._dht.isStarted).to.equal(true)
|
||||
expect(libp2p._dht.isStarted).to.equal(true)
|
||||
})
|
||||
})
|
@ -9,9 +9,9 @@ const pWaitFor = require('p-wait-for')
|
||||
const mergeOptions = require('merge-options')
|
||||
const multiaddr = require('multiaddr')
|
||||
|
||||
const { create } = require('../../src')
|
||||
const { create } = require('../../../src')
|
||||
const { subsystemOptions, subsystemMulticodecs } = require('./utils')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
const peerUtils = require('../../utils/creators/peer')
|
||||
|
||||
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/8000')
|
||||
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/8001')
|
||||
@ -22,7 +22,7 @@ describe('DHT subsystem operates correctly', () => {
|
||||
let remAddr
|
||||
|
||||
beforeEach(async () => {
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
remotePeerInfo.multiaddrs.add(remoteListenAddr)
|
||||
@ -57,8 +57,8 @@ describe('DHT subsystem operates correctly', () => {
|
||||
expect(connection).to.exist()
|
||||
|
||||
return Promise.all([
|
||||
pWaitFor(() => libp2p._dht._dht.routingTable.size === 1),
|
||||
pWaitFor(() => remoteLibp2p._dht._dht.routingTable.size === 1)
|
||||
pWaitFor(() => libp2p._dht.routingTable.size === 1),
|
||||
pWaitFor(() => remoteLibp2p._dht.routingTable.size === 1)
|
||||
])
|
||||
})
|
||||
|
||||
@ -69,13 +69,13 @@ describe('DHT subsystem operates correctly', () => {
|
||||
await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
|
||||
|
||||
await Promise.all([
|
||||
pWaitFor(() => libp2p._dht._dht.routingTable.size === 1),
|
||||
pWaitFor(() => remoteLibp2p._dht._dht.routingTable.size === 1)
|
||||
pWaitFor(() => libp2p._dht.routingTable.size === 1),
|
||||
pWaitFor(() => remoteLibp2p._dht.routingTable.size === 1)
|
||||
])
|
||||
|
||||
await libp2p._dht.put(key, value)
|
||||
await libp2p.contentRouting.put(key, value)
|
||||
|
||||
const fetchedValue = await remoteLibp2p._dht.get(key)
|
||||
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
||||
expect(fetchedValue).to.eql(value)
|
||||
})
|
||||
})
|
||||
@ -110,11 +110,11 @@ describe('DHT subsystem operates correctly', () => {
|
||||
const connection = await libp2p.dial(remAddr)
|
||||
|
||||
expect(connection).to.exist()
|
||||
expect(libp2p._dht._dht.routingTable.size).to.be.eql(0)
|
||||
expect(remoteLibp2p._dht._dht.routingTable.size).to.be.eql(0)
|
||||
expect(libp2p._dht.routingTable.size).to.be.eql(0)
|
||||
expect(remoteLibp2p._dht.routingTable.size).to.be.eql(0)
|
||||
|
||||
await remoteLibp2p._dht.start()
|
||||
return pWaitFor(() => libp2p._dht._dht.routingTable.size === 1)
|
||||
return pWaitFor(() => libp2p._dht.routingTable.size === 1)
|
||||
})
|
||||
|
||||
it('should put on a peer and get from the other', async () => {
|
||||
@ -124,11 +124,11 @@ describe('DHT subsystem operates correctly', () => {
|
||||
const value = Buffer.from('world')
|
||||
|
||||
await remoteLibp2p._dht.start()
|
||||
await pWaitFor(() => libp2p._dht._dht.routingTable.size === 1)
|
||||
await pWaitFor(() => libp2p._dht.routingTable.size === 1)
|
||||
|
||||
await libp2p._dht.put(key, value)
|
||||
await libp2p.contentRouting.put(key, value)
|
||||
|
||||
const fetchedValue = await remoteLibp2p._dht.get(key)
|
||||
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
||||
expect(fetchedValue).to.eql(value)
|
||||
})
|
||||
})
|
@ -2,7 +2,7 @@
|
||||
|
||||
const KadDht = require('libp2p-kad-dht')
|
||||
const { multicodec } = require('libp2p-kad-dht')
|
||||
const Crypto = require('../../src/insecure/plaintext')
|
||||
const Crypto = require('../../../src/insecure/plaintext')
|
||||
const Muxer = require('libp2p-mplex')
|
||||
const Transport = require('libp2p-tcp')
|
||||
|
24
test/content-routing/utils.js
Normal file
24
test/content-routing/utils.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
const KadDht = require('libp2p-kad-dht')
|
||||
const mergeOptions = require('merge-options')
|
||||
const baseOptions = require('../utils/base-options')
|
||||
|
||||
module.exports.baseOptions = baseOptions
|
||||
|
||||
const routingOptions = mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
dht: KadDht
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
randomWalk: {
|
||||
enabled: true
|
||||
},
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
module.exports.routingOptions = routingOptions
|
@ -18,7 +18,7 @@ describe('Listening', () => {
|
||||
let libp2p
|
||||
|
||||
before(async () => {
|
||||
[peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
[peerInfo] = await peerUtils.createPeerInfo()
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
})
|
||||
|
||||
|
@ -10,7 +10,7 @@ const sinon = require('sinon')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { collect } = require('streaming-iterables')
|
||||
const pipe = require('it-pipe')
|
||||
const { createPeerInfoFromFixture } = require('../utils/creators/peer')
|
||||
const { createPeerInfo } = require('../utils/creators/peer')
|
||||
const baseOptions = require('../utils/base-options')
|
||||
const Libp2p = require('../../src')
|
||||
const { codes: Errors } = require('../../src/errors')
|
||||
@ -21,7 +21,7 @@ describe('Dialing (via relay, TCP)', () => {
|
||||
let dstLibp2p
|
||||
|
||||
before(async () => {
|
||||
const peerInfos = await createPeerInfoFromFixture(3)
|
||||
const peerInfos = await createPeerInfo({ number: 3 })
|
||||
// Create 3 nodes, and turn HOP on for the relay
|
||||
;[srcLibp2p, relayLibp2p, dstLibp2p] = peerInfos.map((peerInfo, index) => {
|
||||
const opts = baseOptions
|
||||
|
@ -15,14 +15,14 @@ const multiaddr = require('multiaddr')
|
||||
|
||||
const Libp2p = require('../../src')
|
||||
const baseOptions = require('../utils/base-options')
|
||||
const { createPeerInfoFromFixture } = require('../utils/creators/peer')
|
||||
const { createPeerInfo } = require('../utils/creators/peer')
|
||||
|
||||
describe('peer discovery scenarios', () => {
|
||||
let peerInfo, remotePeerInfo1, remotePeerInfo2
|
||||
let libp2p
|
||||
|
||||
before(async () => {
|
||||
[peerInfo, remotePeerInfo1, remotePeerInfo2] = await createPeerInfoFromFixture(3)
|
||||
[peerInfo, remotePeerInfo1, remotePeerInfo2] = await createPeerInfo({ number: 3 })
|
||||
|
||||
peerInfo.multiaddrs.add(multiaddr('/ip4/127.0.0.1/tcp/0'))
|
||||
remotePeerInfo1.multiaddrs.add(multiaddr('/ip4/127.0.0.1/tcp/0'))
|
||||
|
@ -13,7 +13,7 @@ const MulticastDNS = require('libp2p-mdns')
|
||||
|
||||
const Libp2p = require('../../src')
|
||||
const baseOptions = require('../utils/base-options.browser')
|
||||
const { createPeerInfoFromFixture } = require('../utils/creators/peer')
|
||||
const { createPeerInfo } = require('../utils/creators/peer')
|
||||
|
||||
describe('peer discovery', () => {
|
||||
let peerInfo
|
||||
@ -21,7 +21,7 @@ describe('peer discovery', () => {
|
||||
let libp2p
|
||||
|
||||
before(async () => {
|
||||
[peerInfo, remotePeerInfo] = await createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await createPeerInfo({ number: 2 })
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
|
219
test/peer-routing/peer-routing.node.js
Normal file
219
test/peer-routing/peer-routing.node.js
Normal file
@ -0,0 +1,219 @@
|
||||
'use strict'
|
||||
/* eslint-env mocha */
|
||||
|
||||
const chai = require('chai')
|
||||
chai.use(require('dirty-chai'))
|
||||
const { expect } = chai
|
||||
const nock = require('nock')
|
||||
const sinon = require('sinon')
|
||||
|
||||
const pDefer = require('p-defer')
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
|
||||
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
const { baseOptions, routingOptions } = require('./utils')
|
||||
|
||||
describe('peer-routing', () => {
|
||||
describe('no routers', () => {
|
||||
let node
|
||||
|
||||
before(async () => {
|
||||
[node] = await peerUtils.createPeer({
|
||||
config: baseOptions
|
||||
})
|
||||
})
|
||||
|
||||
it('.findPeer should return an error', async () => {
|
||||
await expect(node.peerRouting.findPeer('a cid'))
|
||||
.to.eventually.be.rejected()
|
||||
.and.to.have.property('code', 'NO_ROUTERS_AVAILABLE')
|
||||
})
|
||||
})
|
||||
|
||||
describe('via dht router', () => {
|
||||
const number = 5
|
||||
let nodes
|
||||
|
||||
before(async () => {
|
||||
nodes = await peerUtils.createPeer({
|
||||
number,
|
||||
config: routingOptions
|
||||
})
|
||||
|
||||
// Ring dial
|
||||
await Promise.all(
|
||||
nodes.map((peer, i) => peer.dial(nodes[(i + 1) % number].peerInfo))
|
||||
)
|
||||
})
|
||||
|
||||
after(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
after(() => Promise.all(nodes.map((n) => n.stop())))
|
||||
|
||||
it('should use the nodes dht', () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(nodes[0]._dht, 'findPeer').callsFake(() => {
|
||||
deferred.resolve()
|
||||
return nodes[1].peerInfo
|
||||
})
|
||||
|
||||
nodes[0].peerRouting.findPeer()
|
||||
return deferred.promise
|
||||
})
|
||||
})
|
||||
|
||||
describe('via delegate router', () => {
|
||||
let node
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
delegate = new DelegatedPeerRouter({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
})
|
||||
|
||||
;[node] = await peerUtils.createPeer({
|
||||
config: mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
peerRouting: [delegate]
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
afterEach(() => node.stop())
|
||||
|
||||
it('should use the delegate router to find peers', async () => {
|
||||
const deferred = pDefer()
|
||||
|
||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||
deferred.resolve()
|
||||
return 'fake peer-info'
|
||||
})
|
||||
|
||||
await node.peerRouting.findPeer()
|
||||
return deferred.promise
|
||||
})
|
||||
|
||||
it('should be able to find a peer', async () => {
|
||||
const peerKey = 'QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL'
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
.post('/api/v0/dht/findpeer')
|
||||
.query({
|
||||
arg: peerKey
|
||||
})
|
||||
.reply(200, `{"Extra":"","ID":"some other id","Responses":null,"Type":0}\n{"Extra":"","ID":"","Responses":[{"Addrs":["/ip4/127.0.0.1/tcp/4001"],"ID":"${peerKey}"}],"Type":2}\n`, [
|
||||
'Content-Type', 'application/json',
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
|
||||
const peerInfo = await node.peerRouting.findPeer(peerKey)
|
||||
|
||||
expect(peerInfo.id.toB58String()).to.equal(peerKey)
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should error when a peer cannot be found', async () => {
|
||||
const peerKey = 'key of a peer not on the network'
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
.post('/api/v0/dht/findpeer')
|
||||
.query({
|
||||
arg: peerKey
|
||||
})
|
||||
.reply(200, '{"Extra":"","ID":"some other id","Responses":null,"Type":6}\n{"Extra":"","ID":"yet another id","Responses":null,"Type":0}\n{"Extra":"routing:not found","ID":"","Responses":null,"Type":3}\n', [
|
||||
'Content-Type', 'application/json',
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
|
||||
await expect(node.peerRouting.findPeer(peerKey))
|
||||
.to.eventually.be.rejected()
|
||||
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
|
||||
it('should handle errors from the api', async () => {
|
||||
const peerKey = 'key of a peer not on the network'
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
.post('/api/v0/dht/findpeer')
|
||||
.query({
|
||||
arg: peerKey
|
||||
})
|
||||
.reply(502)
|
||||
|
||||
await expect(node.peerRouting.findPeer(peerKey))
|
||||
.to.eventually.be.rejected()
|
||||
|
||||
expect(mockApi.isDone()).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('via dht and delegate routers', () => {
|
||||
let node
|
||||
let delegate
|
||||
|
||||
beforeEach(async () => {
|
||||
delegate = new DelegatedPeerRouter({
|
||||
host: '0.0.0.0',
|
||||
protocol: 'http',
|
||||
port: 60197
|
||||
})
|
||||
|
||||
;[node] = await peerUtils.createPeer({
|
||||
config: mergeOptions(routingOptions, {
|
||||
modules: {
|
||||
peerRouting: [delegate]
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
afterEach(() => node.stop())
|
||||
|
||||
it('should only use the dht if it finds the peer', async () => {
|
||||
const dhtDeferred = pDefer()
|
||||
|
||||
sinon.stub(node._dht, 'findPeer').callsFake(() => {
|
||||
dhtDeferred.resolve()
|
||||
return node.peerInfo
|
||||
})
|
||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||
throw new Error('the delegate should not have been called')
|
||||
})
|
||||
|
||||
await node.peerRouting.findPeer('a peer id')
|
||||
await dhtDeferred.promise
|
||||
})
|
||||
|
||||
it('should use the delegate if the dht fails to find the peer', async () => {
|
||||
const results = [true]
|
||||
|
||||
sinon.stub(node._dht, 'findPeer').callsFake(() => {})
|
||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||
return results
|
||||
})
|
||||
|
||||
const peer = await node.peerRouting.findPeer('a peer id')
|
||||
expect(peer).to.eql(results)
|
||||
})
|
||||
})
|
||||
})
|
24
test/peer-routing/utils.js
Normal file
24
test/peer-routing/utils.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
const KadDht = require('libp2p-kad-dht')
|
||||
const mergeOptions = require('merge-options')
|
||||
const baseOptions = require('../utils/base-options')
|
||||
|
||||
module.exports.baseOptions = baseOptions
|
||||
|
||||
const routingOptions = mergeOptions(baseOptions, {
|
||||
modules: {
|
||||
dht: KadDht
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
randomWalk: {
|
||||
enabled: true
|
||||
},
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
module.exports.routingOptions = routingOptions
|
@ -34,7 +34,7 @@ describe('peer-store', () => {
|
||||
sinon.spy(peerStore, 'add')
|
||||
sinon.spy(peerStore, 'update')
|
||||
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
|
||||
peerStore.on('peer', (peer) => {
|
||||
expect(peer).to.exist()
|
||||
@ -51,7 +51,7 @@ describe('peer-store', () => {
|
||||
})
|
||||
|
||||
it('should update peer when it is already in the store', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
|
||||
// Put the peer in the store
|
||||
peerStore.put(peerInfo)
|
||||
@ -82,7 +82,7 @@ describe('peer-store', () => {
|
||||
|
||||
it('should emit the "change:multiaddrs" event when a peer has new multiaddrs', async () => {
|
||||
const defer = pDefer()
|
||||
const [createdPeerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [createdPeerInfo] = await peerUtils.createPeerInfo()
|
||||
|
||||
// Put the peer in the store
|
||||
peerStore.put(createdPeerInfo)
|
||||
@ -110,7 +110,7 @@ describe('peer-store', () => {
|
||||
|
||||
it('should emit the "change:protocols" event when a peer has new protocols', async () => {
|
||||
const defer = pDefer()
|
||||
const [createdPeerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [createdPeerInfo] = await peerUtils.createPeerInfo()
|
||||
|
||||
// Put the peer in the store
|
||||
peerStore.put(createdPeerInfo)
|
||||
@ -137,7 +137,7 @@ describe('peer-store', () => {
|
||||
})
|
||||
|
||||
it('should be able to retrieve a peer from store through its b58str id', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
const id = peerInfo.id.toB58String()
|
||||
|
||||
let retrievedPeer = peerStore.get(id)
|
||||
@ -154,7 +154,7 @@ describe('peer-store', () => {
|
||||
})
|
||||
|
||||
it('should be able to remove a peer from store through its b58str id', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfo(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
const id = peerInfo.id.toB58String()
|
||||
|
||||
let removed = peerStore.remove(id)
|
||||
@ -177,7 +177,7 @@ describe('peer-store on dial', () => {
|
||||
let remoteLibp2p
|
||||
|
||||
before(async () => {
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
remoteLibp2p = new Libp2p(mergeOptions(baseOptions, {
|
||||
peerInfo: remotePeerInfo
|
||||
}))
|
||||
|
@ -32,7 +32,7 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
it('should start and stop by default once libp2p starts', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
@ -50,7 +50,7 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
it('should not start if disabled once libp2p starts', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
@ -70,7 +70,7 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
it('should allow a manual start', async () => {
|
||||
const [peerInfo] = await peerUtils.createPeerInfoFromFixture(1)
|
||||
const [peerInfo] = await peerUtils.createPeerInfo()
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
|
||||
const customOptions = mergeOptions(subsystemOptions, {
|
||||
|
@ -29,7 +29,7 @@ describe('Pubsub subsystem is able to use different implementations', () => {
|
||||
let remAddr
|
||||
|
||||
beforeEach(async () => {
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
remotePeerInfo.multiaddrs.add(remoteListenAddr)
|
||||
|
@ -24,7 +24,7 @@ describe('Pubsub subsystem operates correctly', () => {
|
||||
let remAddr
|
||||
|
||||
beforeEach(async () => {
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
|
||||
peerInfo.multiaddrs.add(listenAddr)
|
||||
remotePeerInfo.multiaddrs.add(remoteListenAddr)
|
||||
|
@ -23,7 +23,7 @@ describe('registrar on dial', () => {
|
||||
let remoteAddr
|
||||
|
||||
before(async () => {
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
remoteLibp2p = new Libp2p(mergeOptions(baseOptions, {
|
||||
peerInfo: remotePeerInfo
|
||||
}))
|
||||
|
@ -11,7 +11,7 @@ module.exports.createMockConnection = async (properties = {}) => {
|
||||
const localAddr = multiaddr('/ip4/127.0.0.1/tcp/8080')
|
||||
const remoteAddr = multiaddr('/ip4/127.0.0.1/tcp/8081')
|
||||
|
||||
const [localPeer, remotePeer] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
const [localPeer, remotePeer] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
const openStreams = []
|
||||
let streamId = 0
|
||||
|
||||
|
@ -1,32 +1,71 @@
|
||||
'use strict'
|
||||
|
||||
const pTimes = require('p-times')
|
||||
|
||||
const multiaddr = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
const PeerInfo = require('peer-info')
|
||||
|
||||
const Libp2p = require('../../../src')
|
||||
const Peers = require('../../fixtures/peers')
|
||||
const defaultOptions = require('../base-options.browser')
|
||||
|
||||
async function createPeerInfo (length) {
|
||||
const peers = await Promise.all(
|
||||
Array.from({ length })
|
||||
.map((_, i) => PeerId.create())
|
||||
)
|
||||
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||
|
||||
return peers.map((peer) => new PeerInfo(peer))
|
||||
/**
|
||||
* Create libp2p nodes.
|
||||
* @param {Object} [properties]
|
||||
* @param {Object} [properties.config]
|
||||
* @param {number} [properties.number] number of peers (default: 1).
|
||||
* @param {boolean} [properties.fixture] use fixture for peer-id generation (default: true)
|
||||
* @param {boolean} [properties.started] nodes should start (defaul: true)
|
||||
* @return {Promise<Array<Libp2p>>}
|
||||
*/
|
||||
async function createPeer ({ number = 1, fixture = true, started = true, config = defaultOptions } = {}) {
|
||||
const peerInfos = await createPeerInfo({ number, fixture })
|
||||
|
||||
const peers = await pTimes(number, (i) => Libp2p.create({
|
||||
peerInfo: peerInfos[i],
|
||||
...config
|
||||
}))
|
||||
|
||||
if (started) {
|
||||
await Promise.all(peers.map((p) => {
|
||||
p.peerInfo.multiaddrs.add(listenAddr)
|
||||
return p.start()
|
||||
}))
|
||||
}
|
||||
|
||||
return peers
|
||||
}
|
||||
|
||||
function createPeerIdsFromFixture (length) {
|
||||
return Promise.all(
|
||||
Array.from({ length })
|
||||
.map((_, i) => PeerId.createFromJSON(Peers[i]))
|
||||
/**
|
||||
* Create Peer-ids.
|
||||
* @param {Object} [properties]
|
||||
* @param {number} [properties.number] number of peers (default: 1).
|
||||
* @param {boolean} [properties.fixture] use fixture for peer-id generation (default: true)
|
||||
* @return {Promise<Array<PeerInfo>>}
|
||||
*/
|
||||
async function createPeerInfo ({ number = 1, fixture = true } = {}) {
|
||||
const peerIds = await createPeerId({ number, fixture })
|
||||
|
||||
return pTimes(number, (i) => PeerInfo.create(peerIds[i]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Peer-ids.
|
||||
* @param {Object} [properties]
|
||||
* @param {number} [properties.number] number of peers (default: 1).
|
||||
* @param {boolean} [properties.fixture] use fixture for peer-id generation (default: true)
|
||||
* @return {Promise<Array<PeerId>>}
|
||||
*/
|
||||
function createPeerId ({ number = 1, fixture = true } = {}) {
|
||||
return pTimes(number, (i) => fixture
|
||||
? PeerId.createFromJSON(Peers[i])
|
||||
: PeerId.create()
|
||||
)
|
||||
}
|
||||
|
||||
async function createPeerInfoFromFixture (length) {
|
||||
const peers = await createPeerIdsFromFixture(length)
|
||||
|
||||
return peers.map((peer) => new PeerInfo(peer))
|
||||
}
|
||||
|
||||
module.exports.createPeer = createPeer
|
||||
module.exports.createPeerInfo = createPeerInfo
|
||||
module.exports.createPeerIdsFromFixture = createPeerIdsFromFixture
|
||||
module.exports.createPeerInfoFromFixture = createPeerInfoFromFixture
|
||||
module.exports.createPeerId = createPeerId
|
||||
|
@ -16,7 +16,7 @@ module.exports = async (properties = {}) => {
|
||||
const localAddr = multiaddr('/ip4/127.0.0.1/tcp/8080')
|
||||
const remoteAddr = multiaddr('/ip4/127.0.0.1/tcp/8081')
|
||||
|
||||
const [localPeer, remotePeer] = await peerUtils.createPeerInfoFromFixture(2)
|
||||
const [localPeer, remotePeer] = await peerUtils.createPeerInfo({ number: 2 })
|
||||
const openStreams = []
|
||||
let streamId = 0
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user