UNPKG

@achingbrain/ssdp

Version:

Yet another SSDP implementation for node.js

73 lines 2.87 kB
import { EventEmitter, on } from 'node:events'; import { createRequire } from 'node:module'; import { advertise } from './advertise/index.js'; import { adverts } from './adverts.js'; import { notify } from './commands/notify.js'; import { search } from './commands/search.js'; import { createSockets } from './create-sockets.js'; import { defaultSsdpOptions } from './default-ssdp-options.js'; import { discover } from './discover/index.js'; import { searchResponse } from './discover/search-response.js'; import { parseSsdpMessage } from './parse-ssdp-message.js'; import { sendSsdpMessage } from './send-ssdp-message.js'; const req = createRequire(import.meta.url); const { name, version } = req('../../package.json'); const DEFAULT_SSDP_SIGNATURE = `node.js/${process.version.substring(1)} UPnP/1.1 ${name}/${version}`; export class SSDP extends EventEmitter { udn; signature; sockets; options; abortController; constructor(options) { super(); this.options = defaultSsdpOptions(options); this.udn = this.options.udn ?? `uuid:${crypto.randomUUID()}`; this.signature = this.options.signature ?? DEFAULT_SSDP_SIGNATURE; this.sockets = []; this.abortController = new AbortController(); } async start() { // set up UDP sockets listening for SSDP broadcasts this.sockets = await createSockets(this, this.abortController.signal); // set up protocol listeners this.on('transport:incoming-message', parseSsdpMessage.bind(null, this)); this.on('ssdp:send-message', sendSsdpMessage.bind(null, this)); this.on('ssdp:m-search', search.bind(null, this)); this.on('ssdp:notify', notify.bind(null, this)); this.on('ssdp:search-response', searchResponse.bind(null, this)); } async stop() { await adverts.stopAll(); await Promise.all(this.sockets.map(async (socket) => { await new Promise(resolve => { socket.on('close', () => { resolve(); }); socket.close(); socket.closed = true; }); })); this.abortController.abort(); } async advertise(advert) { return advertise(this, advert); } async *discover(serviceType) { const opts = typeof serviceType === 'string' ? { serviceType } : serviceType; discover(this, opts?.serviceType); let interval; if (opts?.searchInterval != null) { interval = setInterval(() => { discover(this, opts?.serviceType); }, opts.searchInterval); } try { for await (const [service] of on(this, 'service:discover', opts)) { yield service; } } finally { clearInterval(interval); } } } //# sourceMappingURL=ssdp.js.map