diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md index a1a5149e..135390eb 100644 --- a/doc/CONFIGURATION.md +++ b/doc/CONFIGURATION.md @@ -781,6 +781,26 @@ By default under nodejs libp2p will attempt to use [UPnP](https://en.wikipedia.o [NAT-PMP](http://miniupnp.free.fr/nat-pmp.html) is a feature of some modern routers which performs a similar job to UPnP. NAT-PMP is disabled by default, if enabled libp2p will try to use NAT-PMP and will fall back to UPnP if it fails. +#### Configuring protocol name + +Changing the protocol name prefix can isolate default public network (IPFS) for custom purposes. + +```js +const node = await Libp2p.create({ + config: { + protocolPrefix: 'ipfs' // default + } +}) +/* +protocols: [ + "/ipfs/id/1.0.0", // identify service protocol (if we have multiplexers) + "/ipfs/id/push/1.0.0", // identify service push protocol (if we have multiplexers) + "/ipfs/ping/1.0.0", // built-in ping protocol +] +*/ +``` + + ## Configuration examples As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration: diff --git a/src/config.js b/src/config.js index bbcc6dab..9542c700 100644 --- a/src/config.js +++ b/src/config.js @@ -57,6 +57,7 @@ const DefaultConfig = { } }, config: { + protocolPrefix: 'ipfs', dht: { enabled: false, kBucketSize: 20, diff --git a/src/identify/consts.js b/src/identify/consts.js index 1f697e5d..7c2484aa 100644 --- a/src/identify/consts.js +++ b/src/identify/consts.js @@ -3,7 +3,13 @@ // @ts-ignore file not listed within the file list of projects const libp2pVersion = require('../../package.json').version -module.exports.PROTOCOL_VERSION = 'ipfs/0.1.0' +module.exports.PROTOCOL_VERSION = 'ipfs/0.1.0' // deprecated module.exports.AGENT_VERSION = `js-libp2p/${libp2pVersion}` -module.exports.MULTICODEC_IDENTIFY = '/ipfs/id/1.0.0' -module.exports.MULTICODEC_IDENTIFY_PUSH = '/ipfs/id/push/1.0.0' +module.exports.MULTICODEC_IDENTIFY = '/ipfs/id/1.0.0' // deprecated +module.exports.MULTICODEC_IDENTIFY_PUSH = '/ipfs/id/push/1.0.0' // deprecated + +module.exports.IDENTIFY_PROTOCOL_VERSION = '0.1.0' +module.exports.MULTICODEC_IDENTIFY_PROTOCOL_NAME = 'id' +module.exports.MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME = 'id/push' +module.exports.MULTICODEC_IDENTIFY_PROTOCOL_VERSION = '1.0.0' +module.exports.MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION = '1.0.0' diff --git a/src/identify/index.js b/src/identify/index.js index 5b85bcf6..5a3b4ff3 100644 --- a/src/identify/index.js +++ b/src/identify/index.js @@ -23,7 +23,11 @@ const PeerRecord = require('../record/peer-record') const { MULTICODEC_IDENTIFY, MULTICODEC_IDENTIFY_PUSH, - PROTOCOL_VERSION + IDENTIFY_PROTOCOL_VERSION, + MULTICODEC_IDENTIFY_PROTOCOL_NAME, + MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME, + MULTICODEC_IDENTIFY_PROTOCOL_VERSION, + MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION } = require('./consts') const { codes } = require('../errors') @@ -39,6 +43,16 @@ const { codes } = require('../errors') */ class IdentifyService { + /** + * @param {import('../')} libp2p + */ + static getProtocolStr (libp2p) { + return { + identifyProtocolStr: `/${libp2p._config.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}`, + identifyPushProtocolStr: `/${libp2p._config.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}` + } + } + /** * @class * @param {Object} options @@ -53,9 +67,13 @@ class IdentifyService { this.handleMessage = this.handleMessage.bind(this) + const protocolStr = IdentifyService.getProtocolStr(libp2p) + this.identifyProtocolStr = protocolStr.identifyProtocolStr + this.identifyPushProtocolStr = protocolStr.identifyPushProtocolStr + // Store self host metadata this._host = { - protocolVersion: PROTOCOL_VERSION, + protocolVersion: `${libp2p._config.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`, ...libp2p._options.host } @@ -94,7 +112,7 @@ class IdentifyService { const pushes = connections.map(async connection => { try { - const { stream } = await connection.newStream(MULTICODEC_IDENTIFY_PUSH) + const { stream } = await connection.newStream(this.identifyPushProtocolStr) await pipe( [Message.Identify.encode({ @@ -129,7 +147,7 @@ class IdentifyService { const connections = [] let connection for (const peer of this.peerStore.peers.values()) { - if (peer.protocols.includes(MULTICODEC_IDENTIFY_PUSH) && (connection = this.connectionManager.get(peer.id))) { + if (peer.protocols.includes(this.identifyPushProtocolStr) && (connection = this.connectionManager.get(peer.id))) { connections.push(connection) } } @@ -147,7 +165,7 @@ class IdentifyService { * @returns {Promise} */ async identify (connection) { - const { stream } = await connection.newStream(MULTICODEC_IDENTIFY) + const { stream } = await connection.newStream(this.identifyProtocolStr) const [data] = await pipe( [], stream, @@ -224,9 +242,9 @@ class IdentifyService { */ handleMessage ({ connection, stream, protocol }) { switch (protocol) { - case MULTICODEC_IDENTIFY: + case this.identifyProtocolStr: return this._handleIdentify({ connection, stream }) - case MULTICODEC_IDENTIFY_PUSH: + case this.identifyPushProtocolStr: return this._handlePush({ connection, stream }) default: log.error('cannot handle unknown protocol %s', protocol) diff --git a/src/index.js b/src/index.js index 999bcb26..3bd1fbfe 100644 --- a/src/index.js +++ b/src/index.js @@ -31,7 +31,6 @@ const PersistentPeerStore = require('./peer-store/persistent') const Registrar = require('./registrar') const ping = require('./ping') const IdentifyService = require('./identify') -const IDENTIFY_PROTOCOLS = IdentifyService.multicodecs const NatManager = require('./nat-manager') const { updateSelfPeerRecord } = require('./record/utils') @@ -289,7 +288,7 @@ class Libp2p extends EventEmitter { // Add the identify service since we can multiplex this.identifyService = new IdentifyService({ libp2p: this }) - this.handle(Object.values(IDENTIFY_PROTOCOLS), this.identifyService.handleMessage) + this.handle(Object.values(IdentifyService.getProtocolStr(this)), this.identifyService.handleMessage) } // Attach private network protector diff --git a/src/ping/constants.js b/src/ping/constants.js index d4c3bd08..8ddd596d 100644 --- a/src/ping/constants.js +++ b/src/ping/constants.js @@ -1,6 +1,8 @@ 'use strict' module.exports = { - PROTOCOL: '/ipfs/ping/1.0.0', - PING_LENGTH: 32 + PROTOCOL: '/ipfs/ping/1.0.0', // deprecated + PING_LENGTH: 32, + PROTOCOL_VERSION: '1.0.0', + PROTOCOL_NAME: 'ping' } diff --git a/src/ping/index.js b/src/ping/index.js index 6ad98852..2ffb139c 100644 --- a/src/ping/index.js +++ b/src/ping/index.js @@ -13,7 +13,7 @@ const { toBuffer } = require('it-buffer') const { collect, take } = require('streaming-iterables') const equals = require('uint8arrays/equals') -const { PROTOCOL, PING_LENGTH } = require('./constants') +const { PROTOCOL_NAME, PING_LENGTH, PROTOCOL_VERSION } = require('./constants') /** * @typedef {import('../')} Libp2p @@ -30,11 +30,12 @@ const { PROTOCOL, PING_LENGTH } = require('./constants') * @returns {Promise} */ async function ping (node, peer) { + const protocol = `/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}` // @ts-ignore multiaddr might not have toB58String - log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer) + log('dialing %s to %s', protocol, peer.toB58String ? peer.toB58String() : peer) const connection = await node.dial(peer) - const { stream } = await connection.newStream(PROTOCOL) + const { stream } = await connection.newStream(protocol) const start = Date.now() const data = crypto.randomBytes(PING_LENGTH) @@ -61,7 +62,7 @@ async function ping (node, peer) { * @param {Libp2p} node */ function mount (node) { - node.handle(PROTOCOL, ({ stream }) => pipe(stream, stream)) + node.handle(`/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`, ({ stream }) => pipe(stream, stream)) } /** @@ -70,7 +71,7 @@ function mount (node) { * @param {Libp2p} node */ function unmount (node) { - node.unhandle(PROTOCOL) + node.unhandle(`/${node._config.protocolPrefix}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`) } exports = module.exports = ping diff --git a/test/configuration/protocol-prefix.node.js b/test/configuration/protocol-prefix.node.js new file mode 100644 index 00000000..6a718e65 --- /dev/null +++ b/test/configuration/protocol-prefix.node.js @@ -0,0 +1,47 @@ +'use strict' +/* eslint-env mocha */ + +const { expect } = require('aegir/utils/chai') +const mergeOptions = require('merge-options') + +const { create } = require('../../src') +const { baseOptions } = require('./utils') + +describe('Protocol prefix is configurable', () => { + let libp2p + + it('protocolPrefix is provided', async () => { + const testProtocol = 'test-protocol' + libp2p = await create(mergeOptions(baseOptions, { + config: { + protocolPrefix: testProtocol + } + })) + + const protocols = libp2p.peerStore.protoBook.get(libp2p.peerId); + [ + '/libp2p/circuit/relay/0.1.0', + `/${testProtocol}/id/1.0.0`, + `/${testProtocol}/id/push/1.0.0`, + `/${testProtocol}/ping/1.0.0` + ].forEach((i, idx) => { + expect(protocols[idx]).equals(i) + }) + await libp2p.stop() + }) + + it('protocolPrefix is not provided', async () => { + libp2p = await create(baseOptions) + + const protocols = libp2p.peerStore.protoBook.get(libp2p.peerId); + [ + '/libp2p/circuit/relay/0.1.0', + '/ipfs/id/1.0.0', + '/ipfs/id/push/1.0.0', + '/ipfs/ping/1.0.0' + ].forEach((i, idx) => { + expect(protocols[idx]).equals(i) + }) + await libp2p.stop() + }) +}) diff --git a/test/identify/index.spec.js b/test/identify/index.spec.js index dbf2d736..2b7ccc6b 100644 --- a/test/identify/index.spec.js +++ b/test/identify/index.spec.js @@ -60,7 +60,8 @@ describe('Identify', () => { peerStore: localPeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) const remoteIdentify = new IdentifyService({ @@ -70,7 +71,8 @@ describe('Identify', () => { peerStore: remotePeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -119,7 +121,8 @@ describe('Identify', () => { peerStore: localPeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: { agentVersion } } + _options: { host: { agentVersion } }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -131,7 +134,8 @@ describe('Identify', () => { peerStore: remotePeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: { agentVersion } } + _options: { host: { agentVersion } }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -180,7 +184,8 @@ describe('Identify', () => { connectionManager: new EventEmitter(), peerStore: localPeerStore, multiaddrs: [], - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) const remoteIdentify = new IdentifyService({ @@ -189,7 +194,8 @@ describe('Identify', () => { connectionManager: new EventEmitter(), peerStore: remotePeerStore, multiaddrs: [], - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -231,7 +237,8 @@ describe('Identify', () => { host: { agentVersion } - } + }, + _config: { protocolPrefix: 'ipfs' } }, protocols }) @@ -261,7 +268,8 @@ describe('Identify', () => { peerStore: localPeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -275,7 +283,8 @@ describe('Identify', () => { peerStore: remotePeerStore, multiaddrs: [], isStarted: () => true, - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -333,7 +342,8 @@ describe('Identify', () => { peerStore: localPeerStore, multiaddrs: listenMaddrs, isStarted: () => true, - _options: { host: {} } + _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' } } }) @@ -347,6 +357,7 @@ describe('Identify', () => { peerStore: new PeerStore({ peerId: remotePeer }), multiaddrs: [], _options: { host: {} }, + _config: { protocolPrefix: 'ipfs' }, isStarted: () => true } })