diff --git a/package.json b/package.json index 9e9e7ca3..c638a672 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "peer-book": "~0.9.0", "peer-id": "~0.12.0", "peer-info": "~0.15.0", + "promisify-es6": "^1.0.3", "rimraf": "^2.6.2", "safe-buffer": "^5.1.2", "stats-lite": "^2.2.0", @@ -68,6 +69,7 @@ "dependencies": { "async": "^2.6.1", "bignumber.js": "^8.0.1", + "callbackify": "^1.1.0", "cids": "~0.7.0", "debug": "^4.1.0", "ipfs-block": "~0.8.0", diff --git a/src/index.js b/src/index.js index 6cb299fd..305636cb 100644 --- a/src/index.js +++ b/src/index.js @@ -37,9 +37,11 @@ const statsKeys = [ * * @param {Libp2p} libp2p * @param {Blockstore} blockstore + * @param {Provider} provider + * @param {object} options */ class Bitswap { - constructor (libp2p, blockstore, options) { + constructor (libp2p, blockstore, provider, options) { this._libp2p = libp2p this._log = logger(this.peerInfo.id) @@ -53,7 +55,7 @@ class Bitswap { }) // the network delivers messages - this.network = new Network(libp2p, this, {}, this._stats) + this.network = new Network(libp2p, this, {}, this._stats, provider) // local database this.blockstore = blockstore diff --git a/src/network.js b/src/network.js index 37ea7cb9..24dd21a6 100644 --- a/src/network.js +++ b/src/network.js @@ -5,6 +5,7 @@ const pull = require('pull-stream') const waterfall = require('async/waterfall') const each = require('async/each') const nextTick = require('async/nextTick') +const callbackify = require('callbackify') const Message = require('./types/message') const CONSTANTS = require('./constants') @@ -14,11 +15,12 @@ const BITSWAP100 = '/ipfs/bitswap/1.0.0' const BITSWAP110 = '/ipfs/bitswap/1.1.0' class Network { - constructor (libp2p, bitswap, options, stats) { + constructor (libp2p, bitswap, options, stats, provider) { this._log = logger(libp2p.peerInfo.id, 'network') options = options || {} this.libp2p = libp2p this.bitswap = bitswap + this.provider = provider this.b100Only = options.b100Only || false this._stats = stats @@ -98,10 +100,14 @@ class Network { } findProviders (cid, maxProviders, callback) { - this.libp2p.contentRouting.findProviders(cid, { - maxTimeout: CONSTANTS.providerRequestTimeout, - maxNumProviders: maxProviders - }, callback) + const findProviders = callbackify((cid, maxProviders) => { + return this.provider.findProviders(cid, { + maxTimeout: CONSTANTS.providerRequestTimeout, + maxNumProviders: maxProviders + }) + }) + + findProviders(cid, maxProviders, callback) } findAndConnect (cid, callback) { @@ -115,7 +121,9 @@ class Network { } provide (cid, callback) { - this.libp2p.contentRouting.provide(cid, callback) + const provide = callbackify((cid) => this.provider.provide(cid)) + + provide(cid, callback) } // Connect to the given peer diff --git a/test/bitswap-mock-internals.js b/test/bitswap-mock-internals.js index 51c179af..998f67d5 100644 --- a/test/bitswap-mock-internals.js +++ b/test/bitswap-mock-internals.js @@ -19,6 +19,7 @@ const Bitswap = require('../src') const createTempRepo = require('./utils/create-temp-repo-nodejs') const mockNetwork = require('./utils/mocks').mockNetwork const applyNetwork = require('./utils/mocks').applyNetwork +const Provider = require('./utils/mocks').mockProvider const mockLibp2pNode = require('./utils/mocks').mockLibp2pNode const storeHasBlocks = require('./utils/store-has-blocks') const makeBlock = require('./utils/make-block') @@ -55,7 +56,10 @@ describe('bitswap with mocks', function () { describe('receive message', () => { it('simple block message', (done) => { - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) + bs.start((err) => { expect(err).to.not.exist() @@ -92,7 +96,10 @@ describe('bitswap with mocks', function () { }) it('simple want message', (done) => { - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) + bs.start((err) => { expect(err).to.not.exist() const other = ids[1] @@ -119,7 +126,9 @@ describe('bitswap with mocks', function () { it('multi peer', function (done) { this.timeout(80 * 1000) - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) let others let blocks @@ -165,7 +174,10 @@ describe('bitswap with mocks', function () { }) it('ignore unwanted blocks', (done) => { - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) + bs.start((err) => { expect(err).to.not.exist() @@ -213,7 +225,10 @@ describe('bitswap with mocks', function () { describe('get', () => { it('fails on requesting empty block', (done) => { - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) + bs.get(null, (err, res) => { expect(err).to.exist() expect(err.message).to.equal('Not a valid cid') @@ -226,7 +241,9 @@ describe('bitswap with mocks', function () { repo.blocks.put(block, (err) => { expect(err).to.not.exist() - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) bs.get(block.cid, (err, res) => { expect(err).to.not.exist() @@ -244,7 +261,9 @@ describe('bitswap with mocks', function () { repo.blocks.putMany([b1, b2, b3], (err) => { expect(err).to.not.exist() - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) bs.getMany([b1.cid, b2.cid, b3.cid], (err, res) => { expect(err).to.not.exist() @@ -262,7 +281,9 @@ describe('bitswap with mocks', function () { repo.blocks.putMany([b1, b2, b3], (err) => { expect(err).to.not.exist() - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) map([b1.cid, b2.cid, b3.cid], (cid, cb) => bs.get(cid, cb), (err, res) => { expect(err).to.not.exist() @@ -275,7 +296,9 @@ describe('bitswap with mocks', function () { it('block is added locally afterwards', (done) => { const finish = orderedFinish(2, done) const block = blocks[9] - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) const net = mockNetwork() bs.network = net @@ -359,7 +382,9 @@ describe('bitswap with mocks', function () { setImmediate(() => callback()) } } - bs1 = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + bs1 = new Bitswap(libp2pNode, repo.blocks, provider) applyNetwork(bs1, n1) bs1.start((err) => { @@ -371,7 +396,9 @@ describe('bitswap with mocks', function () { (cb) => createTempRepo(cb), (repo, cb) => { repo2 = repo - bs2 = new Bitswap(mockLibp2pNode(), repo2.blocks) + const libp2pNode2 = mockLibp2pNode() + const provider2 = new Provider(libp2pNode) + bs2 = new Bitswap(libp2pNode2, repo2.blocks, provider2) applyNetwork(bs2, n2) bs2.start((err) => { expect(err).to.not.exist() @@ -397,7 +424,9 @@ describe('bitswap with mocks', function () { it('double get', (done) => { const block = blocks[11] - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) parallel( [ @@ -420,7 +449,10 @@ describe('bitswap with mocks', function () { describe('unwant', () => { it('removes blocks that are wanted multiple times', (done) => { - const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + const libp2pNode = mockLibp2pNode() + const provider = new Provider(libp2pNode) + const bs = new Bitswap(libp2pNode, repo.blocks, provider) + bs.start((err) => { expect(err).to.not.exist() const b = blocks[12] diff --git a/test/bitswap-stats.js b/test/bitswap-stats.js index 5e0a8521..dc5f3d79 100644 --- a/test/bitswap-stats.js +++ b/test/bitswap-stats.js @@ -15,6 +15,7 @@ const Message = require('../src/types/message') const Bitswap = require('../src') const createTempRepo = require('./utils/create-temp-repo-nodejs') +const Provider = require('./utils/mocks').mockProvider const createLibp2pNode = require('./utils/create-libp2p-node') const makeBlock = require('./utils/make-block') const countToFinish = require('./utils/helpers').countToFinish @@ -81,11 +82,14 @@ describe('bitswap stats', () => { }) before(() => { - bitswaps = nodes.map((node, i) => - new Bitswap(libp2pNodes[i], repos[i].blocks, { + bitswaps = nodes.map((node, i) => { + const provider = new Provider(libp2pNodes[i]) + + return new Bitswap(libp2pNodes[i], repos[i].blocks, provider, { statsEnabled: true, statsComputeThrottleTimeout: 500 // fast update interval for tests - })) + }) + }) bs = bitswaps[0] bs.wm.wantBlocks(blocks.map(b => b.cid)) }) diff --git a/test/bitswap.js b/test/bitswap.js index ec1b52f2..8d868336 100644 --- a/test/bitswap.js +++ b/test/bitswap.js @@ -16,6 +16,7 @@ const Bitswap = require('../src') const createTempRepo = require('./utils/create-temp-repo-nodejs') const createLibp2pNode = require('./utils/create-libp2p-node') const makeBlock = require('./utils/make-block') +const Provider = require('./utils/mocks').mockProvider const orderedFinish = require('./utils/helpers').orderedFinish // Creates a repo + libp2pNode + Bitswap with or without DHT @@ -28,7 +29,8 @@ function createThing (dht, callback) { }, (err, node) => cb(err, repo, node)) }, (repo, libp2pNode, cb) => { - const bitswap = new Bitswap(libp2pNode, repo.blocks) + const provider = new Provider(libp2pNode) + const bitswap = new Bitswap(libp2pNode, repo.blocks, provider) bitswap.start((err) => cb(err, repo, libp2pNode, bitswap)) } ], (err, repo, libp2pNode, bitswap) => { diff --git a/test/utils/mocks.js b/test/utils/mocks.js index 3f84fedb..68b0e66c 100644 --- a/test/utils/mocks.js +++ b/test/utils/mocks.js @@ -6,6 +6,7 @@ const map = require('async/map') const parallel = require('async/parallel') const setImmediate = require('async/setImmediate') const series = require('async/series') +const promisify = require('promisify-es6') const _ = require('lodash') const PeerId = require('peer-id') const PeerInfo = require('peer-info') @@ -17,6 +18,35 @@ const EventEmitter = require('events') const Bitswap = require('../../src') +/* + * Create a mock provider + */ + +class Provider { + constructor (libp2p) { + this._contentRouting = libp2p.contentRouting + } + + /** + * Announce block to the network and add and entry to the tracker + * Takes a cid and makes an attempt to announce it to the network + * @param {CID} cid + */ + async provide (cid) { + await promisify((callback) => { + this._contentRouting.provide(cid, callback) + })() + } + + async findProviders (cid, options) { // eslint-disable-line require-await + return promisify((callback) => { + this._contentRouting.findProviders(cid, options, callback) + })() + } +} + +exports.mockProvider = Provider + /* * Create a mock libp2p node */ @@ -206,7 +236,9 @@ exports.genBitswapNetwork = (n, callback) => { // create every BitSwap function createBitswaps () { netArray.forEach((net) => { - net.bitswap = new Bitswap(net.libp2p, net.repo.blocks, net.peerBook) + const provider = new Provider(net.libp2p) + + net.bitswap = new Bitswap(net.libp2p, net.repo.blocks, provider, net.peerBook) }) establishLinks() }