ui
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build-publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: yarn install
|
||||
- run: yarn build
|
||||
- run: git config --global user.name "ON LX Team"
|
||||
- run: git config --global user.email "team@onlx.ltd"
|
||||
- run: npm version ${{ github.event.release.tag_name }} --allow-same-version
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
node_js:
|
||||
- '6'
|
||||
- '5'
|
||||
- '4'
|
||||
- '0.12'
|
||||
- '0.10'
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (https://github.com/onlxltd/bonjour-service) (c) 2021 ON LX Limited
|
||||
|
||||
Portions Copyright (Bonjour - https://github.com/watson/bonjour) (c) 2015-2016 Thomas Watson Steen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
# bonjour-service
|
||||
|
||||
    [](https://deepscan.io/dashboard#view=project&tid=13435&pid=16430&bid=352351)
|
||||
|
||||
A Bonjour/Zeroconf protocol implementation in TypeScript. Publish
|
||||
services on the local network or discover existing services using
|
||||
multicast DNS.
|
||||
|
||||
This is a rewrite of the project Bonjour (https://github.com/watson/bonjour) into modern TypeScript.
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
Add to your project dependencies using Yarn or NPM.
|
||||
|
||||
#### Install with Yarn
|
||||
```
|
||||
yarn add bonjour-service
|
||||
```
|
||||
#### Install with NPM
|
||||
```
|
||||
npm install bonjour-service
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import Bonjour from 'bonjour-service'
|
||||
|
||||
const instance = new Bonjour()
|
||||
|
||||
// advertise an HTTP server on port 3000
|
||||
instance.publish({ name: 'My Web Server', type: 'http', port: 3000 })
|
||||
|
||||
// browse for all http services
|
||||
instance.find({ type: 'http' }, function (service) {
|
||||
console.log('Found an HTTP server:', service)
|
||||
})
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Initializing
|
||||
|
||||
```js
|
||||
var instance = new Bonjour({ options })
|
||||
```
|
||||
|
||||
The `options` are optional and will be used when initializing the
|
||||
underlying multicast-dns server. For details see [the multicast-dns
|
||||
documentation](https://github.com/mafintosh/multicast-dns#mdns--multicastdnsoptions).
|
||||
|
||||
### Publishing
|
||||
|
||||
#### `var service = bonjour.publish(options)`
|
||||
|
||||
Publishes a new service.
|
||||
|
||||
Options are:
|
||||
|
||||
- `name` (string)
|
||||
- `host` (string, optional) - defaults to local hostname
|
||||
- `port` (number)
|
||||
- `type` (string)
|
||||
- `subtypes` (array of strings, optional)
|
||||
- `protocol` (string, optional) - `udp` or `tcp` (default)
|
||||
- `txt` (object, optional) - a key/value object to broadcast as the TXT
|
||||
record
|
||||
|
||||
IANA maintains a [list of official service types and port
|
||||
numbers](http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml).
|
||||
|
||||
#### `bonjour.unpublishAll([callback])`
|
||||
|
||||
Unpublish all services. The optional `callback` will be called when the
|
||||
services have been unpublished.
|
||||
|
||||
#### `bonjour.destroy()`
|
||||
|
||||
Destroy the mdns instance. Closes the udp socket.
|
||||
|
||||
### Browser
|
||||
|
||||
#### `var browser = bonjour.find(options[, onup])`
|
||||
|
||||
Listen for services advertised on the network. An optional callback can
|
||||
be provided as the 2nd argument and will be added as an event listener
|
||||
for the `up` event.
|
||||
|
||||
Options (all optional):
|
||||
|
||||
- `type` (string)
|
||||
- `subtypes` (array of strings)
|
||||
- `protocol` (string) - defaults to `tcp`
|
||||
- `txt` (object) - passed into [dns-txt
|
||||
module](https://github.com/watson/dns-txt) contructor. Set to `{
|
||||
binary: true }` if you want to keep the TXT records in binary
|
||||
|
||||
#### `var browser = bonjour.findOne(options[, callback])`
|
||||
|
||||
Listen for and call the `callback` with the first instance of a service
|
||||
matching the `options`. If no `callback` is given, it's expected that
|
||||
you listen for the `up` event. The returned `browser` will automatically
|
||||
stop it self after the first matching service.
|
||||
|
||||
Options are the same as given in the `browser.find` function.
|
||||
|
||||
#### `Event: up`
|
||||
|
||||
Emitted every time a new service is found that matches the browser.
|
||||
|
||||
#### `Event: down`
|
||||
|
||||
Emitted every time an existing service emmits a goodbye message.
|
||||
|
||||
#### `browser.services()`
|
||||
|
||||
An array of services known by the browser to be online.
|
||||
|
||||
#### `browser.start()`
|
||||
|
||||
Start looking for matching services.
|
||||
|
||||
#### `browser.stop()`
|
||||
|
||||
Stop looking for matching services.
|
||||
|
||||
#### `browser.update()`
|
||||
|
||||
Broadcast the query again.
|
||||
|
||||
### Service
|
||||
|
||||
#### `Event: up`
|
||||
|
||||
Emitted when the service is up.
|
||||
|
||||
#### `Event: error`
|
||||
|
||||
Emitted if an error occurrs while publishing the service.
|
||||
|
||||
#### `service.stop([callback])`
|
||||
|
||||
Unpublish the service. The optional `callback` will be called when the
|
||||
service have been unpublished.
|
||||
|
||||
#### `service.start()`
|
||||
|
||||
Publish the service.
|
||||
|
||||
#### `service.name`
|
||||
|
||||
The name of the service, e.g. `Apple TV`.
|
||||
|
||||
#### `service.type`
|
||||
|
||||
The type of the service, e.g. `http`.
|
||||
|
||||
#### `service.subtypes`
|
||||
|
||||
An array of subtypes. Note that this property might be `null`.
|
||||
|
||||
#### `service.protocol`
|
||||
|
||||
The protocol used by the service, e.g. `tcp`.
|
||||
|
||||
#### `service.host`
|
||||
|
||||
The hostname or ip address where the service resides.
|
||||
|
||||
#### `service.port`
|
||||
|
||||
The port on which the service listens, e.g. `5000`.
|
||||
|
||||
#### `service.fqdn`
|
||||
|
||||
The fully qualified domain name of the service. E.g. if given the name
|
||||
`Foo Bar`, the type `http` and the protocol `tcp`, the `service.fqdn`
|
||||
property will be `Foo Bar._http._tcp.local`.
|
||||
|
||||
#### `service.txt`
|
||||
|
||||
The TXT record advertised by the service (a key/value object). Note that
|
||||
this property might be `null`.
|
||||
|
||||
#### `service.published`
|
||||
|
||||
A boolean indicating if the service is currently published.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import Browser, { BrowserConfig } from './lib/browser';
|
||||
import Service, { ServiceConfig, ServiceReferer } from './lib/service';
|
||||
export declare class Bonjour {
|
||||
private server;
|
||||
private registry;
|
||||
constructor(opts?: ServiceConfig | undefined);
|
||||
publish(opts: ServiceConfig): Service;
|
||||
unpublishAll(callback?: CallableFunction | undefined): void;
|
||||
find(opts?: BrowserConfig | undefined, onup?: (...args: any[]) => void): Browser;
|
||||
findOne(opts: BrowserConfig | undefined, timeout: number | undefined, callback: CallableFunction): Browser;
|
||||
destroy(): void;
|
||||
}
|
||||
export { Service, ServiceReferer, Browser };
|
||||
export default Bonjour;
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Browser = exports.Service = exports.Bonjour = void 0;
|
||||
const registry_1 = __importDefault(require("./lib/registry"));
|
||||
const mdns_server_1 = __importDefault(require("./lib/mdns-server"));
|
||||
const browser_1 = __importDefault(require("./lib/browser"));
|
||||
exports.Browser = browser_1.default;
|
||||
const service_1 = __importDefault(require("./lib/service"));
|
||||
exports.Service = service_1.default;
|
||||
class Bonjour {
|
||||
constructor(opts) {
|
||||
this.server = new mdns_server_1.default(opts);
|
||||
this.registry = new registry_1.default(this.server);
|
||||
}
|
||||
publish(opts) {
|
||||
return this.registry.publish(opts);
|
||||
}
|
||||
unpublishAll(callback) {
|
||||
return this.registry.unpublishAll(callback);
|
||||
}
|
||||
find(opts = undefined, onup) {
|
||||
return new browser_1.default(this.server.mdns, opts, onup);
|
||||
}
|
||||
findOne(opts = undefined, timeout = 10000, callback) {
|
||||
const browser = new browser_1.default(this.server.mdns, opts);
|
||||
var timer;
|
||||
browser.once('up', (service) => {
|
||||
if (timer !== undefined)
|
||||
clearTimeout(timer);
|
||||
browser.stop();
|
||||
if (callback)
|
||||
callback(service);
|
||||
});
|
||||
timer = setTimeout(() => {
|
||||
browser.stop();
|
||||
if (callback)
|
||||
callback(null);
|
||||
}, timeout);
|
||||
return browser;
|
||||
}
|
||||
destroy() {
|
||||
this.registry.destroy();
|
||||
this.server.mdns.destroy();
|
||||
}
|
||||
}
|
||||
exports.Bonjour = Bonjour;
|
||||
exports.default = Bonjour;
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AACA,8DAAyD;AACzD,oEAA4D;AAC5D,4DAAwD;AA6EtB,kBA7E3B,iBAAO,CA6E2B;AA5EzC,4DAAwE;AA4E/D,kBA5EF,iBAAO,CA4EE;AA1EhB,MAAa,OAAO;IAShB,YAAY,IAAgC;QACxC,IAAI,CAAC,MAAM,GAAO,IAAI,qBAAM,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,CAAC,QAAQ,GAAK,IAAI,kBAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/C,CAAC;IAOM,OAAO,CAAC,IAAmB;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,CAAC;IAOM,YAAY,CAAC,QAAuC;QACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC/C,CAAC;IAQM,IAAI,CAAC,OAAkC,SAAS,EAAE,IAA+B;QACpF,OAAO,IAAI,iBAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IACpD,CAAC;IASM,OAAO,CAAC,OAAkC,SAAS,EAAE,OAAO,GAAG,KAAK,EAAE,QAA0B;QACnG,MAAM,OAAO,GAAY,IAAI,iBAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC5D,IAAI,KAAU,CAAA;QACd,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAgB,EAAE,EAAE;YACpC,IAAG,KAAK,KAAK,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;YAC3C,OAAO,CAAC,IAAI,EAAE,CAAA;YACd,IAAG,QAAQ;gBAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC,CAAC,CAAA;QACF,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACpB,OAAO,CAAC,IAAI,EAAE,CAAA;YACd,IAAG,QAAQ;gBAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC,EAAE,OAAO,CAAC,CAAA;QACX,OAAO,OAAO,CAAA;IAClB,CAAC;IAKM,OAAO;QACV,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;IAC9B,CAAC;CAEJ;AAxED,0BAwEC;AAID,kBAAe,OAAO,CAAA"}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/// <reference types="node" />
|
||||
import { EventEmitter } from 'events';
|
||||
export interface BrowserConfig {
|
||||
type: string;
|
||||
protocol?: 'tcp' | 'udp';
|
||||
subtypes?: Array<string>;
|
||||
txt?: any;
|
||||
}
|
||||
export declare class Browser extends EventEmitter {
|
||||
private mdns;
|
||||
private onresponse;
|
||||
private serviceMap;
|
||||
private txt;
|
||||
private name?;
|
||||
private wildcard;
|
||||
private _services;
|
||||
constructor(mdns: any, opts: any, onup?: (...args: any[]) => void);
|
||||
start(): void;
|
||||
stop(): void;
|
||||
update(): void;
|
||||
get services(): any[];
|
||||
private addService;
|
||||
private removeService;
|
||||
private goodbyes;
|
||||
private buildServicesFor;
|
||||
}
|
||||
export default Browser;
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Browser = void 0;
|
||||
const events_1 = require("events");
|
||||
const service_types_1 = require("./service-types");
|
||||
const dns_txt_1 = __importDefault(require("./dns-txt"));
|
||||
const dnsEqual = require('dns-equal');
|
||||
const TLD = '.local';
|
||||
const WILDCARD = '_services._dns-sd._udp' + TLD;
|
||||
class Browser extends events_1.EventEmitter {
|
||||
constructor(mdns, opts, onup) {
|
||||
super();
|
||||
this.onresponse = null;
|
||||
this.serviceMap = {};
|
||||
this.wildcard = false;
|
||||
this._services = [];
|
||||
if (typeof opts === 'function')
|
||||
return new Browser(mdns, null, opts);
|
||||
this.mdns = mdns;
|
||||
if (opts != null && opts.txt != null) {
|
||||
this.txt = new dns_txt_1.default(opts.txt);
|
||||
}
|
||||
else {
|
||||
this.txt = new dns_txt_1.default();
|
||||
}
|
||||
if (!opts || !opts.type) {
|
||||
this.name = WILDCARD;
|
||||
this.wildcard = true;
|
||||
}
|
||||
else {
|
||||
this.name = (0, service_types_1.toString)({ name: opts.type, protocol: opts.protocol || 'tcp' }) + TLD;
|
||||
if (opts.name)
|
||||
this.name = opts.name + '.' + this.name;
|
||||
this.wildcard = false;
|
||||
}
|
||||
if (onup)
|
||||
this.on('up', onup);
|
||||
this.start();
|
||||
}
|
||||
start() {
|
||||
if (this.onresponse || this.name === undefined)
|
||||
return;
|
||||
var self = this;
|
||||
var nameMap = {};
|
||||
if (!this.wildcard)
|
||||
nameMap[this.name] = true;
|
||||
this.onresponse = (packet, rinfo) => {
|
||||
if (self.wildcard) {
|
||||
packet.answers.forEach((answer) => {
|
||||
if (answer.type !== 'PTR' || answer.name !== self.name || answer.name in nameMap)
|
||||
return;
|
||||
nameMap[answer.data] = true;
|
||||
self.mdns.query(answer.data, 'PTR');
|
||||
});
|
||||
}
|
||||
Object.keys(nameMap).forEach(function (name) {
|
||||
self.goodbyes(name, packet).forEach(self.removeService.bind(self));
|
||||
var matches = self.buildServicesFor(name, packet, self.txt, rinfo);
|
||||
if (matches.length === 0)
|
||||
return;
|
||||
matches.forEach((service) => {
|
||||
if (self.serviceMap[service.fqdn])
|
||||
return;
|
||||
self.addService(service);
|
||||
});
|
||||
});
|
||||
};
|
||||
this.mdns.on('response', this.onresponse);
|
||||
this.update();
|
||||
}
|
||||
stop() {
|
||||
if (!this.onresponse)
|
||||
return;
|
||||
this.mdns.removeListener('response', this.onresponse);
|
||||
this.onresponse = null;
|
||||
}
|
||||
update() {
|
||||
this.mdns.query(this.name, 'PTR');
|
||||
}
|
||||
get services() {
|
||||
return this._services;
|
||||
}
|
||||
addService(service) {
|
||||
this._services.push(service);
|
||||
this.serviceMap[service.fqdn] = true;
|
||||
this.emit('up', service);
|
||||
}
|
||||
removeService(fqdn) {
|
||||
var service, index;
|
||||
this._services.some(function (s, i) {
|
||||
if (dnsEqual(s.fqdn, fqdn)) {
|
||||
service = s;
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!service || index === undefined)
|
||||
return;
|
||||
this._services.splice(index, 1);
|
||||
delete this.serviceMap[fqdn];
|
||||
this.emit('down', service);
|
||||
}
|
||||
goodbyes(name, packet) {
|
||||
return packet.answers.concat(packet.additionals)
|
||||
.filter((rr) => rr.type === 'PTR' && rr.ttl === 0 && dnsEqual(rr.name, name))
|
||||
.map((rr) => rr.data);
|
||||
}
|
||||
buildServicesFor(name, packet, txt, referer) {
|
||||
var records = packet.answers.concat(packet.additionals).filter((rr) => rr.ttl > 0);
|
||||
return records
|
||||
.filter((rr) => rr.type === 'PTR' && dnsEqual(rr.name, name))
|
||||
.map((ptr) => {
|
||||
var service = {
|
||||
addresses: []
|
||||
};
|
||||
records
|
||||
.filter((rr) => {
|
||||
return (rr.type === 'SRV' || rr.type === 'TXT') && dnsEqual(rr.name, ptr.data);
|
||||
})
|
||||
.forEach((rr) => {
|
||||
if (rr.type === 'SRV') {
|
||||
var parts = rr.name.split('.');
|
||||
var name = parts[0];
|
||||
var types = (0, service_types_1.toType)(parts.slice(1, -1).join('.'));
|
||||
service.name = name;
|
||||
service.fqdn = rr.name;
|
||||
service.host = rr.data.target;
|
||||
service.referer = referer;
|
||||
service.port = rr.data.port;
|
||||
service.type = types.name;
|
||||
service.protocol = types.protocol;
|
||||
service.subtypes = types.subtypes;
|
||||
}
|
||||
else if (rr.type === 'TXT') {
|
||||
service.rawTxt = rr.data;
|
||||
service.txt = this.txt.decodeAll(rr.data);
|
||||
}
|
||||
});
|
||||
if (!service.name)
|
||||
return;
|
||||
records
|
||||
.filter((rr) => (rr.type === 'A' || rr.type === 'AAAA') && dnsEqual(rr.name, service.host))
|
||||
.forEach((rr) => service.addresses.push(rr.data));
|
||||
return service;
|
||||
})
|
||||
.filter((rr) => !!rr);
|
||||
}
|
||||
}
|
||||
exports.Browser = Browser;
|
||||
exports.default = Browser;
|
||||
//# sourceMappingURL=browser.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+12
@@ -0,0 +1,12 @@
|
||||
/// <reference types="node" />
|
||||
declare type KeyValue = {
|
||||
[key: string]: any;
|
||||
};
|
||||
export declare class DnsTxt {
|
||||
private binary;
|
||||
constructor(opts?: KeyValue);
|
||||
encode(data?: KeyValue): Buffer[];
|
||||
decode(buffer: Buffer): KeyValue;
|
||||
decodeAll(buffer: Array<Buffer>): KeyValue;
|
||||
}
|
||||
export default DnsTxt;
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DnsTxt = void 0;
|
||||
class DnsTxt {
|
||||
constructor(opts = {}) {
|
||||
this.binary = opts ? opts.binary : false;
|
||||
}
|
||||
encode(data = {}) {
|
||||
return Object.entries(data)
|
||||
.map(([key, value]) => {
|
||||
let item = `${key}=${value}`;
|
||||
return Buffer.from(item);
|
||||
});
|
||||
}
|
||||
decode(buffer) {
|
||||
var data = {};
|
||||
try {
|
||||
let format = buffer.toString();
|
||||
let parts = format.split(/=(.+)/);
|
||||
let key = parts[0];
|
||||
let value = parts[1];
|
||||
data[key] = value;
|
||||
}
|
||||
catch (_) { }
|
||||
return data;
|
||||
}
|
||||
decodeAll(buffer) {
|
||||
return buffer
|
||||
.filter(i => i.length > 1)
|
||||
.map(i => this.decode(i))
|
||||
.reduce((prev, curr) => {
|
||||
var obj = prev;
|
||||
let [key] = Object.keys(curr);
|
||||
let [value] = Object.values(curr);
|
||||
obj[key] = value;
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
exports.DnsTxt = DnsTxt;
|
||||
exports.default = DnsTxt;
|
||||
//# sourceMappingURL=dns-txt.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"dns-txt.js","sourceRoot":"","sources":["../../src/lib/dns-txt.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAIZ,MAAa,MAAM;IAIf,YAAY,OAAiB,EAAE;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IAC5C,CAAC;IAOM,MAAM,CAAC,OAAiB,EAAE;QAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;aAC1B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAClB,IAAI,IAAI,GAAW,GAAG,GAAG,IAAI,KAAK,EAAE,CAAA;YACpC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC,CAAC,CAAA;IACN,CAAC;IAOM,MAAM,CAAC,MAAc;QACxB,IAAI,IAAI,GAAa,EAAE,CAAA;QAEvB,IAAI;YACA,IAAI,MAAM,GAAoB,MAAM,CAAC,QAAQ,EAAE,CAAA;YAC/C,IAAI,KAAK,GAAqB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACnD,IAAI,GAAG,GAAuB,KAAK,CAAC,CAAC,CAAC,CAAA;YACtC,IAAI,KAAK,GAAqB,KAAK,CAAC,CAAC,CAAC,CAAA;YACtC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;SACpB;QAAC,OAAM,CAAC,EAAE,GAAE;QAEb,OAAO,IAAI,CAAA;IACf,CAAC;IAOM,SAAS,CAAC,MAAqB;QAClC,OAAO,MAAM;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;aACzB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;aACxB,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACnB,IAAI,GAAG,GAAW,IAAI,CAAA;YACtB,IAAI,CAAC,GAAG,CAAC,GAAS,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACnC,IAAI,CAAC,KAAK,CAAC,GAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACrC,GAAG,CAAC,GAAG,CAAC,GAAU,KAAK,CAAA;YACvB,OAAO,GAAG,CAAA;QACd,CAAC,EAAE,EAAE,CAAC,CAAA;IACV,CAAC;CAEJ;AA1DD,wBA0DC;AAED,kBAAe,MAAM,CAAA"}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { ServiceRecord } from './service';
|
||||
export declare class Server {
|
||||
mdns: any;
|
||||
private registry;
|
||||
constructor(opts: any);
|
||||
register(records: Array<ServiceRecord> | ServiceRecord): void;
|
||||
unregister(records: Array<ServiceRecord> | ServiceRecord): void;
|
||||
private respondToQuery;
|
||||
private recordsFor;
|
||||
private isDuplicateRecord;
|
||||
private unique;
|
||||
}
|
||||
export default Server;
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Server = void 0;
|
||||
const array_flatten_1 = __importDefault(require("array-flatten"));
|
||||
const es6_1 = __importDefault(require("fast-deep-equal/es6"));
|
||||
const MulticastDNS = require('multicast-dns');
|
||||
const dnsEqual = require('dns-equal');
|
||||
class Server {
|
||||
constructor(opts) {
|
||||
this.registry = {};
|
||||
this.mdns = MulticastDNS(opts);
|
||||
this.mdns.setMaxListeners(0);
|
||||
this.mdns.on('query', this.respondToQuery.bind(this));
|
||||
}
|
||||
register(records) {
|
||||
const shouldRegister = (record) => {
|
||||
var subRegistry = this.registry[record.type];
|
||||
if (!subRegistry) {
|
||||
subRegistry = this.registry[record.type] = [];
|
||||
}
|
||||
else if (subRegistry.some(this.isDuplicateRecord(record))) {
|
||||
return;
|
||||
}
|
||||
subRegistry.push(record);
|
||||
};
|
||||
if (Array.isArray(records)) {
|
||||
records.forEach(shouldRegister);
|
||||
}
|
||||
else {
|
||||
shouldRegister(records);
|
||||
}
|
||||
}
|
||||
unregister(records) {
|
||||
const shouldUnregister = (record) => {
|
||||
let type = record.type;
|
||||
if (!(type in this.registry)) {
|
||||
return;
|
||||
}
|
||||
this.registry[type] = this.registry[type].filter((i) => i.name !== record.name);
|
||||
};
|
||||
if (Array.isArray(records)) {
|
||||
records.forEach(shouldUnregister);
|
||||
}
|
||||
else {
|
||||
shouldUnregister(records);
|
||||
}
|
||||
}
|
||||
respondToQuery(query) {
|
||||
let self = this;
|
||||
query.questions.forEach((question) => {
|
||||
var type = question.type;
|
||||
var name = question.name;
|
||||
var answers = type === 'ANY'
|
||||
? array_flatten_1.default.depth(Object.keys(self.registry).map(self.recordsFor.bind(self, name)), 1)
|
||||
: self.recordsFor(name, type);
|
||||
if (answers.length === 0)
|
||||
return;
|
||||
var additionals = [];
|
||||
if (type !== 'ANY') {
|
||||
answers.forEach((answer) => {
|
||||
if (answer.type !== 'PTR')
|
||||
return;
|
||||
additionals = additionals
|
||||
.concat(self.recordsFor(answer.data, 'SRV'))
|
||||
.concat(self.recordsFor(answer.data, 'TXT'));
|
||||
});
|
||||
additionals
|
||||
.filter(function (record) {
|
||||
return record.type === 'SRV';
|
||||
})
|
||||
.map(function (record) {
|
||||
return record.data.target;
|
||||
})
|
||||
.filter(this.unique())
|
||||
.forEach(function (target) {
|
||||
additionals = additionals
|
||||
.concat(self.recordsFor(target, 'A'))
|
||||
.concat(self.recordsFor(target, 'AAAA'));
|
||||
});
|
||||
}
|
||||
self.mdns.respond({ answers: answers, additionals: additionals }, (err) => {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
}
|
||||
recordsFor(name, type) {
|
||||
if (!(type in this.registry)) {
|
||||
return [];
|
||||
}
|
||||
return this.registry[type].filter((record) => {
|
||||
var _name = ~name.indexOf('.') ? record.name : record.name.split('.')[0];
|
||||
return dnsEqual(_name, name);
|
||||
});
|
||||
}
|
||||
isDuplicateRecord(a) {
|
||||
return (b) => {
|
||||
return a.type === b.type &&
|
||||
a.name === b.name &&
|
||||
(0, es6_1.default)(a.data, b.data);
|
||||
};
|
||||
}
|
||||
unique() {
|
||||
var set = [];
|
||||
return (obj) => {
|
||||
if (~set.indexOf(obj))
|
||||
return false;
|
||||
set.push(obj);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.Server = Server;
|
||||
exports.default = Server;
|
||||
//# sourceMappingURL=mdns-server.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mdns-server.js","sourceRoot":"","sources":["../../src/lib/mdns-server.ts"],"names":[],"mappings":"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"}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import Server from './mdns-server';
|
||||
import Service, { ServiceConfig } from './service';
|
||||
export declare class Registry {
|
||||
private server;
|
||||
private services;
|
||||
private activated;
|
||||
constructor(server: Server);
|
||||
publish(config: ServiceConfig): Service;
|
||||
unpublishAll(callback: CallableFunction | undefined): void;
|
||||
destroy(): void;
|
||||
private start;
|
||||
private stop;
|
||||
private probe;
|
||||
private announce;
|
||||
private teardown;
|
||||
}
|
||||
export default Registry;
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Registry = void 0;
|
||||
const array_flatten_1 = __importDefault(require("array-flatten"));
|
||||
const service_1 = __importDefault(require("./service"));
|
||||
const dnsEqual = require('dns-equal');
|
||||
const REANNOUNCE_MAX_MS = 60 * 60 * 1000;
|
||||
const REANNOUNCE_FACTOR = 3;
|
||||
class Registry {
|
||||
constructor(server) {
|
||||
this.services = [];
|
||||
this.activated = false;
|
||||
this.server = server;
|
||||
}
|
||||
publish(config) {
|
||||
let service = new service_1.default(config);
|
||||
service.start = this.start.bind(service, this);
|
||||
service.stop = this.stop.bind(service, this);
|
||||
service.start({ probe: config.probe !== false });
|
||||
return service;
|
||||
}
|
||||
unpublishAll(callback) {
|
||||
this.teardown(this.server, this.services, callback);
|
||||
this.services = [];
|
||||
}
|
||||
destroy() {
|
||||
this.services.map(service => service.destroyed = true);
|
||||
}
|
||||
start(registry, opts) {
|
||||
if (this.activated)
|
||||
return;
|
||||
this.activated = true;
|
||||
registry.services.push(this);
|
||||
if (!(this instanceof service_1.default))
|
||||
return;
|
||||
if (opts.probe) {
|
||||
var service = this;
|
||||
registry.probe(registry.server.mdns, this, (exists) => {
|
||||
if (exists) {
|
||||
service.stop();
|
||||
console.log(new Error('Service name is already in use on the network'));
|
||||
return;
|
||||
}
|
||||
registry.announce(registry.server, service);
|
||||
});
|
||||
}
|
||||
else {
|
||||
registry.announce(registry.server, this);
|
||||
}
|
||||
}
|
||||
stop(registry, callback) {
|
||||
if (!this.activated)
|
||||
return;
|
||||
if (!(this instanceof service_1.default))
|
||||
return;
|
||||
registry.teardown(registry.server, this, callback);
|
||||
var index = registry.services.indexOf(this);
|
||||
if (index !== -1)
|
||||
registry.services.splice(index, 1);
|
||||
}
|
||||
probe(mdns, service, callback) {
|
||||
var sent = false;
|
||||
var retries = 0;
|
||||
var timer;
|
||||
const send = () => {
|
||||
if (!service.activated || service.destroyed)
|
||||
return;
|
||||
mdns.query(service.fqdn, 'ANY', function () {
|
||||
sent = true;
|
||||
timer = setTimeout(++retries < 3 ? send : done, 250);
|
||||
timer.unref();
|
||||
});
|
||||
};
|
||||
const onresponse = (packet) => {
|
||||
if (!sent)
|
||||
return;
|
||||
if (packet.answers.some(matchRR) || packet.additionals.some(matchRR))
|
||||
done(true);
|
||||
};
|
||||
const matchRR = (rr) => {
|
||||
return dnsEqual(rr.name, service.fqdn);
|
||||
};
|
||||
const done = (exists) => {
|
||||
mdns.removeListener('response', onresponse);
|
||||
clearTimeout(timer);
|
||||
callback(!!exists);
|
||||
};
|
||||
mdns.on('response', onresponse);
|
||||
setTimeout(send, Math.random() * 250);
|
||||
}
|
||||
announce(server, service) {
|
||||
var delay = 1000;
|
||||
var packet = service.records();
|
||||
server.register(packet);
|
||||
const broadcast = () => {
|
||||
if (!service.activated || service.destroyed)
|
||||
return;
|
||||
server.mdns.respond(packet, function () {
|
||||
if (!service.published) {
|
||||
service.activated = true;
|
||||
service.published = true;
|
||||
service.emit('up');
|
||||
}
|
||||
delay = delay * REANNOUNCE_FACTOR;
|
||||
if (delay < REANNOUNCE_MAX_MS && !service.destroyed) {
|
||||
setTimeout(broadcast, delay).unref();
|
||||
}
|
||||
});
|
||||
};
|
||||
broadcast();
|
||||
}
|
||||
teardown(server, services, callback) {
|
||||
if (!Array.isArray(services))
|
||||
services = [services];
|
||||
services = services.filter((service) => service.activated);
|
||||
var records = array_flatten_1.default.depth(services.map(function (service) {
|
||||
service.activated = false;
|
||||
var records = service.records();
|
||||
records.forEach((record) => {
|
||||
record.ttl = 0;
|
||||
});
|
||||
return records;
|
||||
}), 1);
|
||||
if (records.length === 0)
|
||||
return callback && callback();
|
||||
server.unregister(records);
|
||||
server.mdns.respond(records, function () {
|
||||
services.forEach(function (service) {
|
||||
service.published = false;
|
||||
});
|
||||
if (typeof callback === "function") {
|
||||
callback.apply(null, arguments);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.Registry = Registry;
|
||||
exports.default = Registry;
|
||||
//# sourceMappingURL=registry.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":";;;;;;AAAA,kEAAwD;AAExD,wDAAmE;AAEnE,MAAM,QAAQ,GAAI,OAAO,CAAC,WAAW,CAAC,CAAA;AAEtC,MAAM,iBAAiB,GAAe,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AACpD,MAAM,iBAAiB,GAAe,CAAC,CAAA;AAEvC,MAAa,QAAQ;IAOjB,YAAY,MAAc;QAJlB,aAAQ,GAAmB,EAAE,CAAA;QAE7B,cAAS,GAAc,KAAK,CAAA;QAGhC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC;IAEM,OAAO,CAAC,MAAqB;QAChC,IAAI,OAAO,GAAO,IAAI,iBAAO,CAAC,MAAM,CAAC,CAAA;QACrC,OAAO,CAAC,KAAK,GAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAChD,OAAO,CAAC,IAAI,GAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAC/C,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC,CAAA;QAChD,OAAO,OAAO,CAAA;IAClB,CAAC;IAEM,YAAY,CAAC,QAAsC;QACtD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QACnD,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACtB,CAAC;IAEM,OAAO;QACV,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IAC1D,CAAC;IAEO,KAAK,CAAC,QAAkB,EAAE,IAAa;QAC3C,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QAErB,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE5B,IAAG,CAAC,CAAC,IAAI,YAAY,iBAAO,CAAC;YAAE,OAAM;QAErC,IAAG,IAAI,CAAC,KAAK,EAAE;YACX,IAAI,OAAO,GAAY,IAAI,CAAA;YAC3B,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,MAAW,EAAE,EAAE;gBACvD,IAAG,MAAM,EAAE;oBACP,OAAO,CAAC,IAAI,EAAE,CAAA;oBACd,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAA;oBACvE,OAAM;iBACT;gBACD,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAC/C,CAAC,CAAC,CAAA;SACL;aAAM;YACH,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;SAC3C;IACL,CAAC;IAEO,IAAI,CAAC,QAAkB,EAAE,QAA2B;QACxD,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAM;QAE3B,IAAG,CAAC,CAAC,IAAI,YAAY,iBAAO,CAAC;YAAE,OAAM;QACrC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QAElD,IAAI,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC3C,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACxD,CAAC;IAYO,KAAK,CAAC,IAAS,EAAE,OAAgB,EAAE,QAA0B;QACjE,IAAI,IAAI,GAAkB,KAAK,CAAA;QAC/B,IAAI,OAAO,GAAe,CAAC,CAAA;QAC3B,IAAI,KAAa,CAAA;QAEjB,MAAM,IAAI,GAAG,GAAG,EAAE;YAEd,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS;gBAAE,OAAM;YAEnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;gBAG5B,IAAI,GAAG,IAAI,CAAA;gBACX,KAAK,GAAG,UAAU,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;gBACpD,KAAK,CAAC,KAAK,EAAE,CAAA;YACjB,CAAC,CAAC,CAAA;QACN,CAAC,CAAA;QAED,MAAM,UAAU,GAAG,CAAC,MAAW,EAAE,EAAE;YAM/B,IAAI,CAAC,IAAI;gBAAE,OAAM;YACjB,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACpF,CAAC,CAAA;QAED,MAAM,OAAO,GAAG,CAAC,EAAW,EAAE,EAAE;YAC5B,OAAO,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1C,CAAC,CAAA;QAED,MAAM,IAAI,GAAG,CAAC,MAAW,EAAE,EAAE;YACzB,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YAC3C,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QACtB,CAAC,CAAA;QAED,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;QAC/B,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAA;IACzC,CAAC;IAWO,QAAQ,CAAE,MAAc,EAAE,OAAgB;QAC9C,IAAI,KAAK,GAAG,IAAI,CAAA;QAChB,IAAI,MAAM,GAAyB,OAAO,CAAC,OAAO,EAAE,CAAA;QAGpD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAEvB,MAAM,SAAS,GAAG,GAAG,EAAE;YACnB,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS;gBAAE,OAAM;YAEnD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;gBAGxB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;oBACpB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;oBACxB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;oBACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;iBACrB;gBACD,KAAK,GAAG,KAAK,GAAG,iBAAiB,CAAA;gBACjC,IAAI,KAAK,GAAG,iBAAiB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;oBACjD,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAA;iBACvC;YACL,CAAC,CAAC,CAAA;QACN,CAAC,CAAA;QACD,SAAS,EAAE,CAAA;IACf,CAAC;IASO,QAAQ,CAAE,MAAc,EAAE,QAAkC,EAAE,QAAa;QAC/E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAE,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAA;QAEnD,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAgB,EAAE,EAAE,CAAE,OAAO,CAAC,SAAS,CAAC,CAAA;QAEpE,IAAI,OAAO,GAAQ,uBAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,OAAO;YAC3D,OAAO,CAAC,SAAS,GAAG,KAAK,CAAA;YACzB,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAA;YAC/B,OAAO,CAAC,OAAO,CAAC,CAAC,MAAqB,EAAE,EAAE;gBACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAA;YAClB,CAAC,CAAC,CAAA;YACF,OAAO,OAAO,CAAA;QAClB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAEN,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,IAAI,QAAQ,EAAE,CAAA;QACvD,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAG1B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YACxB,QAA2B,CAAC,OAAO,CAAC,UAAU,OAAO;gBAClD,OAAO,CAAC,SAAS,GAAG,KAAK,CAAA;YAC7B,CAAC,CAAC,CAAA;YACF,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;gBAChC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;aAClC;QACL,CAAC,CAAC,CAAA;IACN,CAAC;CACJ;AAvLD,4BAuLC;AAED,kBAAe,QAAQ,CAAA"}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
export interface ServiceType {
|
||||
name?: string;
|
||||
protocol?: 'tcp' | 'udp' | string | null | undefined;
|
||||
subtypes?: Array<string>;
|
||||
}
|
||||
export declare const toString: (data: ServiceType) => any;
|
||||
export declare const toType: (string: string) => ServiceType;
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.toType = exports.toString = void 0;
|
||||
const Prefix = (name) => {
|
||||
return '_' + name;
|
||||
};
|
||||
const AllowedProp = (key) => {
|
||||
let keys = ['name', 'protocol', 'subtypes'];
|
||||
return keys.includes(key);
|
||||
};
|
||||
const toString = (data) => {
|
||||
let formatted = {
|
||||
name: data.name,
|
||||
protocol: data.protocol,
|
||||
subtypes: data.subtypes
|
||||
};
|
||||
let entries = Object.entries(formatted);
|
||||
return entries
|
||||
.filter(([key, val]) => AllowedProp(key) && val !== undefined)
|
||||
.reduce((prev, [key, val]) => {
|
||||
switch (typeof val) {
|
||||
case 'object':
|
||||
val.map((i) => prev.push(Prefix(i)));
|
||||
break;
|
||||
default:
|
||||
prev.push(Prefix(val));
|
||||
break;
|
||||
}
|
||||
return prev;
|
||||
}, [])
|
||||
.join('.');
|
||||
};
|
||||
exports.toString = toString;
|
||||
const toType = (string) => {
|
||||
var parts = string.split('.');
|
||||
for (let i in parts) {
|
||||
if (parts[i][0] !== '_')
|
||||
continue;
|
||||
parts[i] = parts[i].slice(1);
|
||||
}
|
||||
return {
|
||||
name: parts.shift(),
|
||||
protocol: parts.shift() || null,
|
||||
subtypes: parts
|
||||
};
|
||||
};
|
||||
exports.toType = toType;
|
||||
//# sourceMappingURL=service-types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"service-types.js","sourceRoot":"","sources":["../../src/lib/service-types.ts"],"names":[],"mappings":";;;AAcA,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE;IACpC,OAAO,GAAG,GAAG,IAAI,CAAA;AACrB,CAAC,CAAA;AAOD,MAAM,WAAW,GAAG,CAAC,GAAW,EAAW,EAAE;IACzC,IAAI,IAAI,GAAkB,CAAC,MAAM,EAAC,UAAU,EAAC,UAAU,CAAC,CAAA;IACxD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC7B,CAAC,CAAA;AAOM,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAO,EAAE;IAE/C,IAAI,SAAS,GAAgB;QACzB,IAAI,EAAU,IAAI,CAAC,IAAI;QACvB,QAAQ,EAAM,IAAI,CAAC,QAAQ;QAC3B,QAAQ,EAAM,IAAI,CAAC,QAAQ;KAC9B,CAAA;IAED,IAAI,OAAO,GAAe,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACnD,OAAO,OAAO;SACT,MAAM,CAAC,CAAC,CAAC,GAAG,EAAC,GAAG,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,SAAS,CAAC;SAC5D,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAC,GAAG,CAAC,EAAE,EAAE;QACxB,QAAO,OAAO,GAAG,EAAE;YACf,KAAK,QAAQ;gBACT,GAAG,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC5C,MAAK;YACT;gBACI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;gBACtB,MAAK;SACZ;QACD,OAAO,IAAI,CAAA;IACf,CAAC,EAAC,EAAE,CAAC;SACJ,IAAI,CAAC,GAAG,CAAC,CAAA;AAClB,CAAC,CAAA;AAvBY,QAAA,QAAQ,YAuBpB;AAOM,MAAM,MAAM,GAAG,CAAC,MAAc,EAAe,EAAE;IAElD,IAAI,KAAK,GAAkB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAE5C,KAAI,IAAI,CAAC,IAAI,KAAK,EAAE;QAChB,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,SAAQ;QACjC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;KAC/B;IAED,OAAO;QACH,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE;QACnB,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,IAAI;QAC/B,QAAQ,EAAE,KAAK;KAClB,CAAA;AACL,CAAC,CAAA;AAdY,QAAA,MAAM,UAclB"}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/// <reference types="node" />
|
||||
import { EventEmitter } from 'events';
|
||||
export interface ServiceConfig {
|
||||
name: string;
|
||||
type: string;
|
||||
port: number;
|
||||
protocol?: 'tcp' | 'udp';
|
||||
host?: string;
|
||||
fqdn?: string;
|
||||
subtypes?: Array<string>;
|
||||
txt?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
probe?: boolean;
|
||||
}
|
||||
export interface ServiceRecord {
|
||||
name: string;
|
||||
type: 'PTR' | 'SRV' | 'TXT' | 'A' | 'AAAA';
|
||||
ttl: number;
|
||||
data: {
|
||||
[key: string]: any;
|
||||
} | string | any;
|
||||
}
|
||||
export interface ServiceReferer {
|
||||
address: string;
|
||||
family: 'IPv4' | 'IPv6';
|
||||
port: number;
|
||||
size: number;
|
||||
}
|
||||
export declare class Service extends EventEmitter {
|
||||
name: string;
|
||||
type: string;
|
||||
protocol: 'tcp' | 'udp';
|
||||
port: number;
|
||||
host: string;
|
||||
fqdn: string;
|
||||
txt?: any;
|
||||
subtypes?: Array<string>;
|
||||
addresses?: Array<string>;
|
||||
referer?: ServiceReferer;
|
||||
probe: boolean;
|
||||
published: boolean;
|
||||
activated: boolean;
|
||||
destroyed: boolean;
|
||||
start?: any;
|
||||
stop?: any;
|
||||
private txtService;
|
||||
constructor(config: ServiceConfig);
|
||||
records(): Array<ServiceRecord>;
|
||||
private RecordPTR;
|
||||
private RecordSRV;
|
||||
private RecordTXT;
|
||||
private RecordA;
|
||||
private RecordAAAA;
|
||||
}
|
||||
export default Service;
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Service = void 0;
|
||||
const os_1 = __importDefault(require("os"));
|
||||
const events_1 = require("events");
|
||||
const service_types_1 = require("./service-types");
|
||||
const dns_txt_1 = __importDefault(require("./dns-txt"));
|
||||
const TLD = '.local';
|
||||
class Service extends events_1.EventEmitter {
|
||||
constructor(config) {
|
||||
super();
|
||||
this.probe = true;
|
||||
this.published = false;
|
||||
this.activated = false;
|
||||
this.destroyed = false;
|
||||
this.txtService = new dns_txt_1.default();
|
||||
this.name = config.name;
|
||||
this.protocol = config.protocol || 'tcp';
|
||||
this.type = (0, service_types_1.toString)({ name: config.type, protocol: this.protocol });
|
||||
this.port = config.port;
|
||||
this.host = config.host || os_1.default.hostname();
|
||||
this.fqdn = `${this.name}.${this.type}${TLD}`;
|
||||
this.txt = config.txt;
|
||||
this.subtypes = config.subtypes;
|
||||
}
|
||||
records() {
|
||||
var records = [this.RecordPTR(this), this.RecordSRV(this), this.RecordTXT(this)];
|
||||
let ifaces = Object.values(os_1.default.networkInterfaces());
|
||||
for (let iface of ifaces) {
|
||||
let addrs = iface;
|
||||
for (let addr of addrs) {
|
||||
if (addr.internal)
|
||||
continue;
|
||||
switch (addr.family) {
|
||||
case 'IPv4':
|
||||
records.push(this.RecordA(this, addr.address));
|
||||
break;
|
||||
case 'IPv6':
|
||||
records.push(this.RecordAAAA(this, addr.address));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return records;
|
||||
}
|
||||
RecordPTR(service) {
|
||||
return {
|
||||
name: `${service.type}${TLD}`,
|
||||
type: 'PTR',
|
||||
ttl: 28800,
|
||||
data: service.fqdn
|
||||
};
|
||||
}
|
||||
RecordSRV(service) {
|
||||
return {
|
||||
name: service.fqdn,
|
||||
type: 'SRV',
|
||||
ttl: 120,
|
||||
data: {
|
||||
port: service.port,
|
||||
target: service.host
|
||||
}
|
||||
};
|
||||
}
|
||||
RecordTXT(service) {
|
||||
return {
|
||||
name: service.fqdn,
|
||||
type: 'TXT',
|
||||
ttl: 4500,
|
||||
data: this.txtService.encode(service.txt)
|
||||
};
|
||||
}
|
||||
RecordA(service, ip) {
|
||||
return {
|
||||
name: service.host,
|
||||
type: 'A',
|
||||
ttl: 120,
|
||||
data: ip
|
||||
};
|
||||
}
|
||||
RecordAAAA(service, ip) {
|
||||
return {
|
||||
name: service.host,
|
||||
type: 'AAAA',
|
||||
ttl: 120,
|
||||
data: ip
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.Service = Service;
|
||||
exports.default = Service;
|
||||
//# sourceMappingURL=service.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/lib/service.ts"],"names":[],"mappings":"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"}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
const { Bonjour } = require('../dist')
|
||||
|
||||
const service = new Bonjour()
|
||||
|
||||
service.publish({ name: 'My Web Server', type: 'http', port: 3000 })
|
||||
|
||||
let browser = service.find({ type: 'http' })
|
||||
|
||||
browser.on('up', (service) => {
|
||||
console.log('up', service)
|
||||
})
|
||||
|
||||
browser.on('down', (service) => {
|
||||
console.log('down', service)
|
||||
})
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "bonjour-service",
|
||||
"version": "1.0.11",
|
||||
"description": "A Bonjour/Zeroconf implementation in TypeScript",
|
||||
"main": "./dist/index.js",
|
||||
"dependencies": {
|
||||
"array-flatten": "^2.1.2",
|
||||
"dns-equal": "^1.0.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"multicast-dns": "^7.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.35",
|
||||
"@typescript-eslint/eslint-plugin": "^4.19.0",
|
||||
"@typescript-eslint/parser": "^4.19.0",
|
||||
"after-all": "^2.0.2",
|
||||
"eslint": "^7.22.0",
|
||||
"standard": "^11.0.0",
|
||||
"tape": "^5.2.2",
|
||||
"ts-node-dev": "^1.1.8",
|
||||
"typescript": "^4.4.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard --fix && tape test/*.js",
|
||||
"build": "tsc --removeComments true",
|
||||
"dev": "ts-node-dev --respawn --transpile-only ./src/index.ts",
|
||||
"example:simple": "node examples/simple"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/onlxltd/bonjour-service.git"
|
||||
},
|
||||
"keywords": [
|
||||
"bonjour",
|
||||
"zeroconf",
|
||||
"zero",
|
||||
"configuration",
|
||||
"mdns",
|
||||
"dns",
|
||||
"service",
|
||||
"discovery",
|
||||
"multicast",
|
||||
"broadcast",
|
||||
"dns-sd"
|
||||
],
|
||||
"author": "ON LX Lited <team@onlx.ltd> (https://labs.onlx.ltd)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/onlxltd/bonjour-service/issues"
|
||||
},
|
||||
"homepage": "https://github.com/onlxltd/bonjour-service"
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
"sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user