diff --git a/src/topology/multicodec-topology.js b/src/topology/multicodec-topology.js index 3e1406a..76ef03d 100644 --- a/src/topology/multicodec-topology.js +++ b/src/topology/multicodec-topology.js @@ -43,11 +43,13 @@ class MulticodecTopology extends Topology { this._registrar = undefined this._onProtocolChange = this._onProtocolChange.bind(this) + this._onPeerConnect = this._onPeerConnect.bind(this) } set registrar (registrar) { this._registrar = registrar this._registrar.peerStore.on('change:protocols', this._onProtocolChange) + this._registrar.connectionManager.on('peer:connect', this._onPeerConnect) // Update topology peers this._updatePeers(this._registrar.peerStore.peers.values()) @@ -97,6 +99,25 @@ class MulticodecTopology extends Topology { } } } + + /** + * Verify if a new connected peer has a topology multicodec and call _onConnect. + * @param {Connection} connection + * @returns {void} + */ + _onPeerConnect (connection) { + const peerId = connection.remotePeer + const protocols = this._registrar.peerStore.protoBook.get(peerId) + + if (!protocols) { + return + } + + if (this.multicodecs.find(multicodec => protocols.includes(multicodec))) { + this.peers.add(peerId.toB58String()) + this._onConnect(peerId, connection) + } + } } module.exports = withIs(MulticodecTopology, { className: 'MulticodecTopology', symbolName: '@libp2p/js-interfaces/topology/multicodec-topology' }) diff --git a/src/topology/tests/multicodec-topology.js b/src/topology/tests/multicodec-topology.js index ec49328..747ad1a 100644 --- a/src/topology/tests/multicodec-topology.js +++ b/src/topology/tests/multicodec-topology.js @@ -96,5 +96,38 @@ module.exports = (test) => { expect(topology._onDisconnect.callCount).to.equal(1) expect(topology._onDisconnect.calledWith(id2)).to.equal(true) }) + + it('should trigger "onConnect" when a peer connects and has one of the topology multicodecs in its known protocols', () => { + sinon.spy(topology, '_onConnect') + sinon.stub(topology._registrar.peerStore.protoBook, 'get').returns(topology.multicodecs) + + topology._registrar.connectionManager.emit('peer:connect', { + remotePeer: id + }) + + expect(topology._onConnect.callCount).to.equal(1) + }) + + it('should not trigger "onConnect" when a peer connects and has none of the topology multicodecs in its known protocols', () => { + sinon.spy(topology, '_onConnect') + sinon.stub(topology._registrar.peerStore.protoBook, 'get').returns([]) + + topology._registrar.connectionManager.emit('peer:connect', { + remotePeer: id + }) + + expect(topology._onConnect.callCount).to.equal(0) + }) + + it('should not trigger "onConnect" when a peer connects and its protocols are not known', () => { + sinon.spy(topology, '_onConnect') + sinon.stub(topology._registrar.peerStore.protoBook, 'get').returns(undefined) + + topology._registrar.connectionManager.emit('peer:connect', { + remotePeer: id + }) + + expect(topology._onConnect.callCount).to.equal(0) + }) }) } diff --git a/test/topology/mock-peer-store.js b/test/topology/mock-peer-store.js index 4dc2729..637d71f 100644 --- a/test/topology/mock-peer-store.js +++ b/test/topology/mock-peer-store.js @@ -6,6 +6,9 @@ class MockPeerStore extends EventEmitter { constructor (peers) { super() this.peers = peers + this.protoBook = { + get: () => {} + } } get (peerId) { diff --git a/test/topology/multicodec-topology.spec.js b/test/topology/multicodec-topology.spec.js index 4723836..09ccc3c 100644 --- a/test/topology/multicodec-topology.spec.js +++ b/test/topology/multicodec-topology.spec.js @@ -1,6 +1,8 @@ /* eslint-env mocha */ 'use strict' +const { EventEmitter } = require('events') + const tests = require('../../src/topology/tests/multicodec-topology') const MulticodecTopology = require('../../src/topology/multicodec-topology') const MockPeerStore = require('./mock-peer-store') @@ -23,9 +25,11 @@ describe('multicodec topology compliance tests', () => { if (!registrar) { const peers = new Map() const peerStore = new MockPeerStore(peers) + const connectionManager = new EventEmitter() registrar = { peerStore, + connectionManager, getConnection: () => { } } }