UNPKG

@ntrip/caster

Version:
132 lines (131 loc) 5.07 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.SocketTransport = void 0; const net = require("net"); const tls = require("tls"); const transport_1 = require("../transport"); const tls_1 = require("tls"); const verror_1 = __importDefault(require("verror")); class SocketTransport extends transport_1.Transport { constructor(manager, options) { super(manager, options); this.options = options; } static new(options) { return (caster) => new SocketTransport(caster, options); } open() { this.server = (this.options.tls === undefined ? net.createServer() : tls.createServer(this.options.tls)); this.server.on('connection', (socket) => this.accept(socket)); new Promise((resolve, reject) => { this.server.once('listening', resolve); this.server.once('error', reject); }).then(() => this.emit('open')) .catch((err) => this.emit('error', err)); this.server.listen(this.options.port); } close() { this.server.close(() => this.emit('close')); } static matchHost(host, mask) { const sections = mask.split('*'); let text = host; for (let section of sections) { const index = text.indexOf(section); if (index < 0) return false; text = text.slice(index + section.length); } return true; } findMatchingSourceHost(socket) { return this.options.sourceHosts.find(sourceHost => SocketTransport.matchHost(socket.remoteAddress, sourceHost.hostMask) && (sourceHost.port === undefined || sourceHost.port === socket.remotePort)); } async accept(socket) { socket.on('error', err => { this.emit('clientError', new verror_1.default({ name: 'ClientError', cause: err, info: { remote: { address: socket.remoteAddress, port: socket.remotePort, family: socket.remoteFamily } } }, "Socket server client error")); }); let sourceHost = this.findMatchingSourceHost(socket); if (sourceHost === undefined) return socket.destroy(); let authResponse; if (sourceHost.authenticate) { const authRequest = { type: sourceHost.type, mountpoint: sourceHost.mountpoint, host: socket.localAddress, source: { host: socket.remoteAddress, port: socket.remotePort, family: socket.remoteFamily }, credentials: { anonymous: !(socket instanceof tls_1.TLSSocket), certificate: socket instanceof tls_1.TLSSocket ? socket.getPeerCertificate().fingerprint : undefined } }; authResponse = await this.caster.authenticate(authRequest); } const source = { protocol: socket instanceof tls_1.TLSSocket ? 'tls' : 'tcp', remote: { host: socket.remoteAddress, port: socket.remotePort, family: socket.remoteFamily }, toString: () => this.connectionDescription(source) }; try { this.connect({ type: sourceHost.type, source: source, mountpoint: sourceHost.mountpoint, gga: sourceHost.gga, str: sourceHost.str, stream: socket, auth: authResponse }); } catch (err) { socket.destroy(err); } } get description() { return `${this.options.tls === undefined ? 'tcp' : 'tls'}[port=${this.options.port}]`; } connectionDescription(source) { return `${source.protocol}://${source.remote.host}:${source.remote.port}`; } } exports.SocketTransport = SocketTransport;