UNPKG

@ntrip/caster

Version:
178 lines (177 loc) 7.82 kB
"use strict"; /* * This file is part of the @ntrip/caster distribution (https://github.com/node-ntrip/caster). * Copyright (c) 2020 Nebojsa Cvetkovic. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Caster = void 0; const events = require("events"); const mountpoint_1 = require("./mountpoint"); const connection_1 = require("./connection"); const sourcetable_1 = require("./sourcetable"); const verror_1 = __importDefault(require("verror")); class Caster extends events.EventEmitter { constructor(parameters) { super(); this._transports = new Set(); this._connections = new Set(); this._mountpoints = new Map(); this.staticSourcetableEntries = []; this.authManager = parameters.authManager; this.mountpointOptions = parameters.mountpointOptions; } get transports() { return this._transports; } ; get connections() { return this._connections; } get mountpoints() { return this._mountpoints; } async authenticate(request) { return this.authManager.authenticate(request); } createMountpoint(mountpointName, options) { if (this._mountpoints.has(mountpointName)) throw new Error("Mountpoint with name \"" + mountpointName + "\" already exists"); if (options === undefined) { if (typeof this.mountpointOptions === "function") { options = this.mountpointOptions(mountpointName); } else { options = this.mountpointOptions; } } const mountpoint = new mountpoint_1.Mountpoint(mountpointName, options); mountpoint.on('close', () => this._mountpoints.delete(mountpointName)); this._mountpoints.set(mountpointName, mountpoint); this.emit('mountpoint', mountpoint); return mountpoint; } prepareMountpoint(type, mountpointName) { let mountpoint = this._mountpoints.get(mountpointName); if (type === 'server') { if (mountpoint === undefined) mountpoint = this.createMountpoint(mountpointName); else if (mountpoint.active) throw new verror_1.default({ name: 'ConnectionError', info: { mountpoint: mountpointName, server: mountpoint.server } }, 'Mountpoint %s conflict: A server is already connected'); } else { // if (type === 'client') { if (mountpoint === undefined || !mountpoint.active) throw new verror_1.default({ name: 'ConnectionError', info: { mountpoint: mountpointName } }, 'Mountpoint %s does not exist (or is not currently active)'); } return mountpoint; } connect(params) { var _a, _b; const mountpoint = this.prepareMountpoint(params.type, params.mountpoint); let connection; const parameters = { ...params, mountpoint: mountpoint, input: (_a = params.input) !== null && _a !== void 0 ? _a : params.stream, output: (_b = params.output) !== null && _b !== void 0 ? _b : params.stream }; if (params.type === 'server') { if (parameters.input === undefined) throw new Error("Missing input stream for server"); connection = new connection_1.Server(parameters); } else { // if (params.type === 'client') { if (parameters.output === undefined) throw new Error("Missing output stream for client"); connection = new connection_1.Client(parameters); } this._connections.add(connection); connection.once('close', () => this._connections.delete(connection)); // Wait for one tick to allow transport to send successful connection message process.nextTick(() => { if (params.type === 'server') { mountpoint.setServer(connection); } else { // if (params.type === 'client') { mountpoint.addClient(connection); } this.emit('connect', connection); }); return connection; } addTransport(constructor) { const transport = constructor(this); this._transports.add(transport); return transport; } removeTransport(transport) { this._transports.delete(transport); } /** * Gets a list of sourcetable entries for the caster with an optional set of filters * * @param filters Optional filters to apply to the sourcetable list * @param auth Authentication request for auth filter */ async getSourcetableEntries(filters, auth) { let entries = Array.from(this._mountpoints.values()).map(m => m.sourceEntry); if (filters !== undefined) { // Include static entries if not filtering by auth if (!filters.auth) entries = this.staticSourcetableEntries.concat(entries); // Filter entries if (filters.simple !== undefined) entries = entries.filter(e => e.filter(filters.simple, true, filters.strict)); if (filters.advanced !== undefined) entries = entries.filter(e => e.filter(filters.advanced, false, filters.strict)); // Filter authentication if (filters === null || filters === void 0 ? void 0 : filters.auth) { if (auth === undefined) throw new Error("Attempting to filter sourcetable entries by authentication without providing authentication request"); const filterResults = await Promise.all(entries.map(async (entry) => { const mountpointAuth = Object.assign({}, auth); mountpointAuth.mountpoint = entry.mountpoint; return (await this.authenticate(mountpointAuth)).authenticated; })); entries = entries.filter((e, i) => filterResults[i]); } // Filter aggregations on all remaining entries if ((filters === null || filters === void 0 ? void 0 : filters.advanced) !== undefined) entries = sourcetable_1.Sourcetable.filterApproximations(filters.advanced, entries, filters.strict); } return entries; } /** * Generates the sourcetable for the caster with an optional set of filters * * @param filters Optional filters to apply to the sourcetable list * @param auth Authentication request for auth filter */ async generateSourcetable(filters, auth) { return (await this.getSourcetableEntries(filters, auth)) .map(e => e.toSourcetableLine()) .concat('ENDSOURCETABLE\r\n').join('\r\n'); } } exports.Caster = Caster; Caster.NAME = 'NodeNtripCaster/0.0.1';