diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 35ddce54dc..e0b670b7d9 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -13,15 +13,20 @@ module.exports = function libp2p (self, config) { const options = self._options || {} config = config || {} - // Always create libp2p via a bundle function - const createBundle = typeof options.libp2p === 'function' - ? options.libp2p - : defaultBundle - const { datastore } = self._repo const peerInfo = self._peerInfo const peerBook = self._peerInfoBook - const libp2p = createBundle({ options, config, datastore, peerInfo, peerBook }) + + const libp2pOptions = getLibp2pOptions({ options, config, datastore, peerInfo, peerBook }) + let libp2p + + if (typeof options.libp2p === 'function') { + libp2p = options.libp2p({ libp2pOptions, options, config, datastore, peerInfo, peerBook }) + } else { + // Required inline to reduce startup time + const Libp2p = require('libp2p') + libp2p = new Libp2p(mergeOptions(libp2pOptions, get(options, 'libp2p', {}))) + } libp2p.on('stop', () => { // Clear our addresses so we can start clean @@ -39,7 +44,7 @@ module.exports = function libp2p (self, config) { return libp2p } -function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { +function getLibp2pOptions ({ options, config, datastore, peerInfo, peerBook }) { // Set up Delegate Routing based on the presence of Delegates in the config let contentRouting let peerRouting @@ -80,7 +85,12 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { peerBook, modules: { contentRouting, - peerRouting, + peerRouting + } + } + + const libp2pOptions = { + modules: { pubsub: getPubsubRouter() }, config: { @@ -133,9 +143,14 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { }) } - const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {})) // Required inline to reduce startup time // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified - const Node = require('../runtime/libp2p-nodejs') - return new Node(libp2pOptions) + const getEnvLibp2pOptions = require('../runtime/libp2p-nodejs') + + // Merge defaults with Node.js/browser/other environments options and configuration + return mergeOptions( + libp2pDefaults, + getEnvLibp2pOptions({ options, config, datastore, peerInfo, peerBook }), + libp2pOptions + ) } diff --git a/src/core/runtime/libp2p-browser.js b/src/core/runtime/libp2p-browser.js index 643fcf108f..7c8a921886 100644 --- a/src/core/runtime/libp2p-browser.js +++ b/src/core/runtime/libp2p-browser.js @@ -8,73 +8,65 @@ const SECIO = require('libp2p-secio') const Bootstrap = require('libp2p-bootstrap') const KadDHT = require('libp2p-kad-dht') const GossipSub = require('libp2p-gossipsub') -const libp2p = require('libp2p') -const mergeOptions = require('merge-options') const multiaddr = require('multiaddr') -class Node extends libp2p { - constructor (_options) { - const wrtcstar = new WebRTCStar({ id: _options.peerInfo.id }) +module.exports = ({ peerInfo, options }) => { + const wrtcstar = new WebRTCStar({ id: peerInfo.id }) - // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 - // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) - const wsstarServers = _options.peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) - _options.peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers - const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: _options.peerInfo.id, ignore_no_online: !wsstarServers.length || _options.wsStarIgnoreErrors }) + // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 + // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) + const wsstarServers = peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) + peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers + const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: peerInfo.id, ignore_no_online: !wsstarServers.length || options.wsStarIgnoreErrors }) - const defaults = { - switch: { - denyTTL: 2 * 60 * 1e3, // 2 minute base - denyAttempts: 5, // back off 5 times - maxParallelDials: 100, - maxColdCalls: 25, - dialTimeout: 20e3 - }, - modules: { - transport: [ - WS, - wrtcstar, - wsstar - ], - streamMuxer: [ - Multiplex - ], - connEncryption: [ - SECIO - ], - peerDiscovery: [ - wrtcstar.discovery, - wsstar.discovery, - Bootstrap - ], - dht: KadDHT, - pubsub: GossipSub - }, - config: { - peerDiscovery: { - autoDial: true, - bootstrap: { - enabled: true - }, - webRTCStar: { - enabled: true - }, - websocketStar: { - enabled: true - } + return { + switch: { + denyTTL: 2 * 60 * 1e3, // 2 minute base + denyAttempts: 5, // back off 5 times + maxParallelDials: 100, + maxColdCalls: 25, + dialTimeout: 20e3 + }, + modules: { + transport: [ + WS, + wrtcstar, + wsstar + ], + streamMuxer: [ + Multiplex + ], + connEncryption: [ + SECIO + ], + peerDiscovery: [ + wrtcstar.discovery, + wsstar.discovery, + Bootstrap + ], + dht: KadDHT, + pubsub: GossipSub + }, + config: { + peerDiscovery: { + autoDial: true, + bootstrap: { + enabled: true }, - dht: { - enabled: false + webRTCStar: { + enabled: true }, - pubsub: { - enabled: true, - emitSelf: true + websocketStar: { + enabled: true } + }, + dht: { + enabled: false + }, + pubsub: { + enabled: true, + emitSelf: true } } - - super(mergeOptions(defaults, _options)) } } - -module.exports = Node diff --git a/src/core/runtime/libp2p-nodejs.js b/src/core/runtime/libp2p-nodejs.js index f124aa4c1f..fb8d488752 100644 --- a/src/core/runtime/libp2p-nodejs.js +++ b/src/core/runtime/libp2p-nodejs.js @@ -9,75 +9,67 @@ const KadDHT = require('libp2p-kad-dht') const GossipSub = require('libp2p-gossipsub') const Multiplex = require('pull-mplex') const SECIO = require('libp2p-secio') -const libp2p = require('libp2p') -const mergeOptions = require('merge-options') const multiaddr = require('multiaddr') -class Node extends libp2p { - constructor (_options) { - // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 - // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) - const wsstarServers = _options.peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) - _options.peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers - const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: _options.peerInfo.id, ignore_no_online: !wsstarServers.length || _options.wsStarIgnoreErrors }) +module.exports = ({ peerInfo, options }) => { + // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 + // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) + const wsstarServers = peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) + peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers + const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: peerInfo.id, ignore_no_online: !wsstarServers.length || options.wsStarIgnoreErrors }) - const defaults = { - switch: { - denyTTL: 2 * 60 * 1e3, // 2 minute base - denyAttempts: 5, // back off 5 times - maxParallelDials: 150, - maxColdCalls: 50, - dialTimeout: 10e3 // Be strict with dial time - }, - modules: { - transport: [ - TCP, - WS, - wsstar - ], - streamMuxer: [ - Multiplex - ], - connEncryption: [ - SECIO - ], - peerDiscovery: [ - MulticastDNS, - Bootstrap, - wsstar.discovery - ], - dht: KadDHT, - pubsub: GossipSub - }, - config: { - peerDiscovery: { - autoDial: true, - mdns: { - enabled: true - }, - bootstrap: { - enabled: true - }, - websocketStar: { - enabled: true - } + return { + switch: { + denyTTL: 2 * 60 * 1e3, // 2 minute base + denyAttempts: 5, // back off 5 times + maxParallelDials: 150, + maxColdCalls: 50, + dialTimeout: 10e3 // Be strict with dial time + }, + modules: { + transport: [ + TCP, + WS, + wsstar + ], + streamMuxer: [ + Multiplex + ], + connEncryption: [ + SECIO + ], + peerDiscovery: [ + MulticastDNS, + Bootstrap, + wsstar.discovery + ], + dht: KadDHT, + pubsub: GossipSub + }, + config: { + peerDiscovery: { + autoDial: true, + mdns: { + enabled: true }, - dht: { - kBucketSize: 20, - enabled: false, - randomWalk: { - enabled: false - } + bootstrap: { + enabled: true }, - pubsub: { - enabled: true, - emitSelf: true + websocketStar: { + enabled: true + } + }, + dht: { + kBucketSize: 20, + enabled: false, + randomWalk: { + enabled: false } + }, + pubsub: { + enabled: true, + emitSelf: true } } - - super(mergeOptions(defaults, _options)) } } - -module.exports = Node diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index 139729dc36..e9d5f47547 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -107,6 +107,39 @@ describe('libp2p customization', function () { done() }) }) + + it('should pass libp2p options to libp2p bundle function', (done) => { + class DummyTransport { + filter () { + return [] + } + } + + const ipfs = { + _repo: { + datastore + }, + _peerInfo: peerInfo, + _peerBook: peerBook, + // eslint-disable-next-line no-console + _print: console.log, + _options: { + libp2p: ({ libp2pOptions, peerInfo }) => { + libp2pOptions.modules.transport = [DummyTransport] + return new Libp2p(libp2pOptions) + } + } + } + + _libp2p = libp2pComponent(ipfs, testConfig) + + _libp2p.start((err) => { + expect(err).to.not.exist() + expect(_libp2p._transport).to.have.length(1) + expect(_libp2p._transport[0] instanceof DummyTransport).to.equal(true) + done() + }) + }) }) describe('options', () => {