diff --git a/lib/browser.js b/lib/browser.js index 92e4795..7b0421e 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -5,8 +5,6 @@ var EventEmitter = require('events').EventEmitter var serviceName = require('multicast-dns-service-types') var txt = require('mdns-txt')() -var TLD = '.local' - module.exports = Browser util.inherits(Browser, EventEmitter) @@ -30,7 +28,12 @@ function Browser (mdns, opts, onup) { if (onup) this.on('up', onup) - this._name = serviceName.stringify(opts.type, opts.protocol || 'tcp') + TLD + this._type = opts.type + this._name = serviceName.stringify({ + name: opts.type, + protocol: opts.protocol || 'tcp', + subtypes: opts.subtypes + }) this._mdns = mdns this._onresponse = null this._serviceMap = {} @@ -46,7 +49,7 @@ Browser.prototype.start = function () { this._onresponse = function (packet) { goodbyes(self._name, packet).forEach(self._removeService.bind(self)) - var matches = buildServicesFor(self._name, packet) + var matches = buildServicesFor(self, packet) if (matches.length === 0) return matches.forEach(function (service) { @@ -97,14 +100,26 @@ function goodbyes (name, packet) { }) } -function buildServicesFor (name, packet) { +function buildServicesFor (browser, packet) { var records = packet.answers.concat(packet.additionals).filter(function (rr) { return rr.ttl > 0 // ignore goodbye messages }) return records .filter(function (rr) { - return rr.name === name && rr.type === 'PTR' + // check the type + if (rr.type !== 'PTR') { + return false + } + + // Check for matching type + var sn = serviceName.parse(rr.name) + if (sn.name !== browser._type) { + return false + } + + // No match + return true }) .map(function (ptr) { var service = { @@ -119,14 +134,14 @@ function buildServicesFor (name, packet) { if (rr.type === 'SRV') { var parts = rr.name.split('.') var name = parts[0] - var types = serviceName.parse(parts.slice(1, -1).join('.')) + var types = serviceName.parse(parts.join('.')) service.name = name service.fqdn = rr.name service.host = rr.data.target service.port = rr.data.port service.type = types.name service.protocol = types.protocol - service.subtypes = types.subtypes + service.subtypes = types.subtypes || [] } else if (rr.type === 'TXT') { service.rawTxt = rr.data service.txt = txt.decode(rr.data) diff --git a/lib/registry.js b/lib/registry.js index 143962a..52ec1e0 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -127,8 +127,6 @@ function announce (server, service) { var delay = 1000 var packet = service._records() - server.register(packet) - ;(function broadcast () { // abort if the service have or is being stopped in the meantime if (!service._activated || service._destroyed) return diff --git a/lib/service.js b/lib/service.js index 3f026eb..f9684cf 100644 --- a/lib/service.js +++ b/lib/service.js @@ -6,8 +6,6 @@ var EventEmitter = require('events').EventEmitter var serviceName = require('multicast-dns-service-types') var txt = require('mdns-txt')() -var TLD = '.local' - module.exports = Service util.inherits(Service, EventEmitter) @@ -19,11 +17,24 @@ function Service (opts) { this.name = opts.name this.protocol = opts.protocol || 'tcp' - this.type = serviceName.stringify(opts.type, this.protocol) + this.type = opts.type || 'http' this.host = opts.host || os.hostname() + + // Sometimes the os reported hostname has the parent name on it + if (this.host.indexOf('.') !== -1) { + var _parts = this.host.split('.') + this.host = _parts[0] + this.parentDomain = opts.parentDomain || _parts[1] + } + this.port = opts.port - this.fqdn = this.name + '.' + this.type + TLD - this.subtypes = opts.subtypes || null + this.subtypes = opts.subtypes || [] + this.fqdn = serviceName.stringify({ + instance: this.name, + name: this.type, + protocol: this.protocol, + parentDomain: this.parentDomain + }) this.txt = opts.txt || null this.published = false @@ -34,9 +45,13 @@ Service.prototype._records = function () { return [rr_ptr(this), rr_srv(this), rr_txt(this)] } -function rr_ptr (service) { +function rr_ptr (service, subtype) { return { - name: service.type + TLD, + name: serviceName.stringify({ + name: service.type, + protocol: service.protocol, + subtypes: service.subtypes + }), type: 'PTR', ttl: 28800, data: service.fqdn @@ -50,7 +65,7 @@ function rr_srv (service) { ttl: 120, data: { port: service.port, - target: service.host + target: service.host + '.' + service.parentDomain } } } diff --git a/package.json b/package.json index ac505f8..5fa3c3c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "mdns-txt": "^2.0.0", "multicast-dns": "^5.0.0", - "multicast-dns-service-types": "^1.1.0" + "multicast-dns-service-types": "git+ssh://git@github.com:wesleytodd/multicast-dns-service-types.git#v2.0.0" }, "devDependencies": { "after-all": "^2.0.2", diff --git a/test/bonjour.js b/test/bonjour.js index 4a03823..a9c8898 100644 --- a/test/bonjour.js +++ b/test/bonjour.js @@ -78,7 +78,7 @@ test('bonjour.find', function (bonjour, t) { setTimeout(function () { bonjour.destroy() t.end() - }, 50) + }, 1000) } }) }) @@ -133,3 +133,49 @@ test('bonjour.findOne - emitter', function (bonjour, t) { bonjour.publish({ name: 'Emitter', type: 'test', port: 3000 }).on('up', next()) bonjour.publish({ name: 'Invalid', type: 'test2', port: 3000 }).on('up', next()) }) + +test('bonjour.findOne - subtype', function (bonjour, t) { + var next = afterAll(function () { + var browser = bonjour.find({ type: 'bar', subtypes: ['sub1'] }) + browser.on('up', function (s) { + t.equal(s.name, 'Foo') + t.equal(s.port, 3000) + // use timeout in an attempt to make sure the invalid record doesn't + // bubble up + setTimeout(function () { + bonjour.destroy() + t.end() + }, 2000) + }) + }) + + bonjour.publish({ name: 'Foo', type: 'bar', port: 3000, subtypes: ['sub1'] }).on('up', next()) + bonjour.publish({ name: 'Invalid', type: 'bar', port: 3001, subtypes: ['sub2'] }).on('up', next()) +}) + +test('bonjour.find - all of subtype', function (bonjour, t) { + var next = afterAll(function () { + var browser = bonjour.find({ type: 'baz' }) + var ups = 0 + + browser.on('up', function (s) { + if (s.name === 'Foo') { + t.equal(s.name, 'Foo') + t.equal(s.fqdn, 'Foo._baz._tcp.local') + t.equal(s.port, 3000) + } else if (s.name === 'Bar') { + t.equal(s.name, 'Bar') + t.equal(s.fqdn, 'Bar._baz._tcp.local') + t.equal(s.port, 3001) + } + + if (++ups === 2) { + bonjour.destroy() + t.end() + } + }) + }) + + bonjour.publish({ name: 'Foo', type: 'baz', port: 3000, subtypes: ['sub1'] }).on('up', next()) + bonjour.publish({ name: 'Bar', type: 'baz', port: 3001, subtypes: ['sub2'] }).on('up', next()) +}) diff --git a/test/service.js b/test/service.js index 275d365..88efef0 100644 --- a/test/service.js +++ b/test/service.js @@ -29,12 +29,12 @@ test('minimal', function (t) { var s = new Service({ name: 'Foo Bar', type: 'http', port: 3000 }) t.equal(s.name, 'Foo Bar') t.equal(s.protocol, 'tcp') - t.equal(s.type, '_http._tcp') - t.equal(s.host, os.hostname()) + t.equal(s.type, 'http') + t.equal(s.host, os.hostname().split('.')[0]) t.equal(s.port, 3000) t.equal(s.fqdn, 'Foo Bar._http._tcp.local') t.equal(s.txt, null) - t.equal(s.subtypes, null) + t.deepEqual(s.subtypes, []) t.equal(s.published, false) t.end() }) @@ -47,7 +47,8 @@ test('protocol', function (t) { test('host', function (t) { var s = new Service({ name: 'Foo Bar', type: 'http', port: 3000, host: 'example.com' }) - t.deepEqual(s.host, 'example.com') + t.deepEqual(s.host, 'example') + t.deepEqual(s.parentDomain, 'com') t.end() }) @@ -59,20 +60,18 @@ test('txt', function (t) { test('_records() - minimal', function (t) { var s = new Service({ name: 'Foo Bar', type: 'http', protocol: 'tcp', port: 3000 }) - t.deepEqual(s._records(), [ - { data: s.fqdn, name: '_http._tcp.local', ttl: 28800, type: 'PTR' }, - { data: { port: 3000, target: os.hostname() }, name: s.fqdn, ttl: 120, type: 'SRV' }, - { data: new Buffer('00', 'hex'), name: s.fqdn, ttl: 4500, type: 'TXT' } - ]) + var r = s._records() + t.deepEqual(r[0], { data: s.fqdn, name: '_http._tcp.local', ttl: 28800, type: 'PTR' }) + t.deepEqual(r[1], { data: { port: 3000, target: os.hostname() }, name: s.fqdn, ttl: 120, type: 'SRV' }) + t.deepEqual(r[2], { data: new Buffer('00', 'hex'), name: s.fqdn, ttl: 4500, type: 'TXT' }) t.end() }) test('_records() - everything', function (t) { - var s = new Service({ name: 'Foo Bar', type: 'http', protocol: 'tcp', port: 3000, host: 'example.com', txt: { foo: 'bar' } }) - t.deepEqual(s._records(), [ - { data: s.fqdn, name: '_http._tcp.local', ttl: 28800, type: 'PTR' }, - { data: { port: 3000, target: 'example.com' }, name: s.fqdn, ttl: 120, type: 'SRV' }, - { data: new Buffer('07666f6f3d626172', 'hex'), name: s.fqdn, ttl: 4500, type: 'TXT' } - ]) + var s = new Service({ name: 'Foo Bar', type: 'http', protocol: 'tcp', port: 3000, host: 'example.com', txt: { foo: 'bar' }, subtypes: ['foo', 'bar'] }) + var r = s._records() + t.deepEqual(r[0], { data: s.fqdn, name: 'foo.bar._sub._http._tcp.local', ttl: 28800, type: 'PTR' }) + t.deepEqual(r[1], { data: { port: 3000, target: 'example.com' }, name: s.fqdn, ttl: 120, type: 'SRV' }) + t.deepEqual(r[2], { data: new Buffer('07666f6f3d626172', 'hex'), name: s.fqdn, ttl: 4500, type: 'TXT' }) t.end() })