diff --git a/README.md b/README.md index 5c271d9..eb6381b 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@ const mdns = new MDNS(peerInfo, options) mdns.on('peer', (peerInfo) => { console.log('Found a peer in the local network', peerInfo.id.toB58String()) }) +process.on('exit', mdns.stop) -// Broadcast for 20 seconds -mdns.start(() => setTimeout(() => mdns.stop(() => {}), 20 * 1000)) +// Listen for peers +mdns.start() ``` - options - - `broadcast` - (true/false) announce our presence through mDNS, default false - - `interval` - query interval, default 10 * 1000 (10 seconds) + - `broadcast` - (true/false) announce our presence through mDNS, default true - `serviceTag` - name of the service announcedm, default 'ipfs.local` diff --git a/src/index.js b/src/index.js index 04f8b95..a9d5293 100644 --- a/src/index.js +++ b/src/index.js @@ -12,11 +12,9 @@ class MulticastDNS extends EventEmitter { options = options || {} this.broadcast = options.broadcast !== false - this.interval = options.interval || (1e3 * 10) this.serviceTag = options.serviceTag || 'ipfs.local' this.port = options.port || 5353 this.peerInfo = peerInfo - this._queryInterval = null } start (callback) { @@ -25,10 +23,11 @@ class MulticastDNS extends EventEmitter { this.mdns = mdns - this._queryInterval = query.queryLAN(this.mdns, this.serviceTag, this.interval) - mdns.on('response', (event) => { - query.gotResponse(event, this.peerInfo, this.serviceTag, (err, foundPeer) => { + if (!self.mdns) { + return + } + query.gotResponse(event, self.peerInfo, self.serviceTag, (err, foundPeer) => { if (err) { return log('Error processing peer response', err) } @@ -38,21 +37,23 @@ class MulticastDNS extends EventEmitter { }) mdns.on('query', (event) => { - query.gotQuery(event, this.mdns, this.peerInfo, this.serviceTag, this.broadcast) + if (!self.mdns) { + return + } + query.gotQuery(event, self.mdns, self.peerInfo, self.serviceTag, self.broadcast) }) - setImmediate(() => callback()) + query.queryLAN(this.mdns, this.serviceTag) + setImmediate(callback) } stop (callback) { - if (!this.mdns) { - callback(new Error('MulticastDNS service had not started yet')) - } else { - clearInterval(this._queryInterval) - this._queryInterval = null - this.mdns.destroy(callback) - this.mdns = undefined + const mdns = this.mdns + if (!mdns) { + return callback(new Error('MulticastDNS service had not started yet')) } + this.mdns = undefined + mdns.destroy(callback) } } diff --git a/src/query.js b/src/query.js index ee39386..551ad46 100644 --- a/src/query.js +++ b/src/query.js @@ -12,19 +12,13 @@ const tcp = new TCP() module.exports = { queryLAN: function (mdns, serviceTag, interval) { - const query = () => { - log('query', serviceTag) - mdns.query({ - questions: [{ - name: serviceTag, - type: 'PTR' - }] - }) - } - - // Immediately start a query, then do it every interval. - query() - return setInterval(query, interval) + log('query', serviceTag) + mdns.query({ + questions: [{ + name: serviceTag, + type: 'PTR' + }] + }) }, gotResponse: function (rsp, peerInfo, serviceTag, callback) { diff --git a/test/multicast-dns.spec.js b/test/multicast-dns.spec.js index f7f1a7b..c672d25 100644 --- a/test/multicast-dns.spec.js +++ b/test/multicast-dns.spec.js @@ -7,11 +7,19 @@ const expect = chai.expect chai.use(dirtyChai) const multiaddr = require('multiaddr') const PeerInfo = require('peer-info') +const PeerId = require('peer-id') const parallel = require('async/parallel') const series = require('async/series') const MulticastDNS = require('./../src') +function createPeer (callback) { + PeerId.create({ bits: 512 }, (err, id) => { + if (err) throw err + PeerInfo.create(id, callback) + }) +} + describe('MulticastDNS', () => { let pA let pB @@ -19,10 +27,9 @@ describe('MulticastDNS', () => { let pD before(function (done) { - this.timeout(80 * 1000) parallel([ (cb) => { - PeerInfo.create((err, peer) => { + createPeer((err, peer) => { expect(err).to.not.exist() pA = peer @@ -31,7 +38,7 @@ describe('MulticastDNS', () => { }) }, (cb) => { - PeerInfo.create((err, peer) => { + createPeer((err, peer) => { expect(err).to.not.exist() pB = peer @@ -41,7 +48,7 @@ describe('MulticastDNS', () => { }) }, (cb) => { - PeerInfo.create((err, peer) => { + createPeer((err, peer) => { expect(err).to.not.exist() pC = peer pC.multiaddrs.add(multiaddr('/ip4/127.0.0.1/tcp/20003')) @@ -50,7 +57,7 @@ describe('MulticastDNS', () => { }) }, (cb) => { - PeerInfo.create((err, peer) => { + createPeer((err, peer) => { if (err) { cb(err) } pD = peer pD.multiaddrs.add(multiaddr('/ip4/127.0.0.1/tcp/30003/ws')) @@ -61,8 +68,6 @@ describe('MulticastDNS', () => { }) it('find another peer', function (done) { - this.timeout(40 * 1000) - const options = { port: 50001 // port must be the same } @@ -72,25 +77,22 @@ describe('MulticastDNS', () => { }) const mdnsB = new MulticastDNS(pB, options) + mdnsA.once('peer', (peerInfo) => { + expect(pB.id.toB58String()).to.eql(peerInfo.id.toB58String()) + parallel([ + (cb) => mdnsA.stop(cb), + (cb) => mdnsB.stop(cb) + ], done) + }) + + mdnsB.once('peer', (peerInfo) => {}) parallel([ (cb) => mdnsA.start(cb), (cb) => mdnsB.start(cb) - ], () => { - mdnsA.once('peer', (peerInfo) => { - expect(pB.id.toB58String()).to.eql(peerInfo.id.toB58String()) - parallel([ - (cb) => mdnsA.stop(cb), - (cb) => mdnsB.stop(cb) - ], done) - }) - - mdnsB.once('peer', (peerInfo) => {}) - }) + ], () => {}) }) it('only announce TCP multiaddrs', function (done) { - this.timeout(40 * 1000) - const options = { port: 50003 // port must be the same } @@ -102,63 +104,55 @@ describe('MulticastDNS', () => { const mdnsC = new MulticastDNS(pC, options) const mdnsD = new MulticastDNS(pD, options) + mdnsA.once('peer', (peerInfo) => { + expect(pC.id.toB58String()).to.eql(peerInfo.id.toB58String()) + expect(peerInfo.multiaddrs.size).to.equal(1) + parallel([ + (cb) => mdnsA.stop(cb), + (cb) => mdnsC.stop(cb), + (cb) => mdnsD.stop(cb) + ], done) + }) + mdnsC.once('peer', (peerInfo) => {}) parallel([ (cb) => mdnsA.start(cb), (cb) => mdnsC.start(cb), (cb) => mdnsD.start(cb) - ], () => { - mdnsA.once('peer', (peerInfo) => { - expect(pC.id.toB58String()).to.eql(peerInfo.id.toB58String()) - expect(peerInfo.multiaddrs.size).to.equal(1) - parallel([ - (cb) => mdnsA.stop(cb), - (cb) => mdnsC.stop(cb), - (cb) => mdnsD.stop(cb) - ], done) - }) - - mdnsC.once('peer', (peerInfo) => {}) - }) + ], () => {}) }) it('announces IP6 addresses', function (done) { - this.timeout(40 * 1000) - const options = { port: 50001 // port must be the same } - const mdnsA = new MulticastDNS(pA, { - broadcast: false, // do not talk to ourself - port: 50001 - }) + const mdnsA = new MulticastDNS(pA, options) const mdnsB = new MulticastDNS(pB, options) + mdnsA.once('peer', (peerInfo) => { + expect(pB.id.toB58String()).to.eql(peerInfo.id.toB58String()) + expect(peerInfo.multiaddrs.size).to.equal(2) + parallel([ + (cb) => mdnsA.stop(cb), + (cb) => mdnsB.stop(cb) + ], done) + }) + mdnsB.once('peer', (peerInfo) => {}) series([ (cb) => mdnsB.start(cb), (cb) => mdnsA.start(cb) - ], () => { - mdnsA.once('peer', (peerInfo) => { - expect(pB.id.toB58String()).to.eql(peerInfo.id.toB58String()) - expect(peerInfo.multiaddrs.size).to.equal(2) - parallel([ - (cb) => mdnsA.stop(cb), - (cb) => mdnsB.stop(cb) - ], done) - }) - - mdnsB.once('peer', (peerInfo) => {}) - }) + ], () => {}) }) it('doesn\'t emit peers after stop', function (done) { - this.timeout(40 * 1000) - const options = { port: 50004 // port must be the same } const mdnsA = new MulticastDNS(pA, options) const mdnsC = new MulticastDNS(pC, options) + mdnsC.once('peer', (peerInfo) => { + done(new Error('Should not receive new peer.')) + }) series([ (cb) => mdnsA.start(cb), @@ -166,10 +160,41 @@ describe('MulticastDNS', () => { (cb) => mdnsA.stop(cb), (cb) => mdnsC.start(cb) ], () => { - setTimeout(() => mdnsC.stop(done), 5000) - mdnsC.once('peer', (peerInfo) => { - done(new Error('Should not receive new peer.')) - }) + setTimeout(() => mdnsC.stop(done), 1000) }) }) + + it('find all peers', function (done) { + const options = { + port: 50001 // port must be the same + } + const mdnsA = new MulticastDNS(pA, options) + const mdnsB = new MulticastDNS(pB, options) + const mdnsC = new MulticastDNS(pC, options) + const peersA = {} + const peersB = {} + const peersC = {} + + // After all the peers have started, each peer should see two other peers. + function check (receiver, peerInfo) { + receiver[peerInfo.id.toB58String()] = true + if (Object.keys(peersA).length === 2 && Object.keys(peersB).length === 2 && Object.keys(peersC).length === 2) { + parallel([ + (cb) => mdnsA.stop(cb), + (cb) => mdnsB.stop(cb), + (cb) => mdnsC.stop(cb) + ], done) + } + } + mdnsA.on('peer', (peerInfo) => check(peersA, peerInfo)) + mdnsB.on('peer', (peerInfo) => check(peersB, peerInfo)) + mdnsC.on('peer', (peerInfo) => check(peersC, peerInfo)) + series([ + (cb) => mdnsA.start(cb), + (cb) => setTimeout(cb, 500), + (cb) => mdnsB.start(cb), + (cb) => setTimeout(cb, 500), + (cb) => mdnsC.start(cb) + ], () => {}) + }) })