/* * This module provides a NodeJS specific implementation of a TLS socket listener * it uses the platform agnostic MqttServer class * @module */ import type { Server } from "node:net"; import { createServer } from "node:tls"; import type { MqttServerOptions } from "../server/mod.ts"; import { MqttServer } from "../server/mod.ts"; import { nodeSocketToNext } from "./nodeSocketToNext.ts"; type ServerOptions = { hostname?: string; port?: number; key: string; cert: string; }; /** * TLS server that wraps a MqttServer, see the /examples folder */ export class TlsServer { /** the MqttServer instance used by the server */ readonly mqttServer: MqttServer; private server?: Server; private serverOptions; /** * Create a new TLS server */ constructor( serverOptions: ServerOptions, mqttOptions: MqttServerOptions | MqttServer, ) { this.serverOptions = serverOptions; if (mqttOptions instanceof MqttServer) { this.mqttServer = mqttOptions; } else { this.mqttServer = new MqttServer(mqttOptions); } } /** * Start listening */ async start(): Promise { const tlsOptions = { minVersion: "TLSv1.3" as const, key: this.serverOptions.key, cert: this.serverOptions.cert, }; this.server = createServer( tlsOptions, (sock) => this.mqttServer.serve(nodeSocketToNext(sock)), ); const isListening = new Promise((resolve) => { this.server?.on("listening", () => { resolve(true); }); }); this.server.listen(this.serverOptions.port, this.serverOptions.hostname); await isListening; return; } /** * Stop listening */ async stop(opts = { closeMqtt: true }): Promise { if (opts.closeMqtt) { await this.mqttServer.close(); } this.server?.close(); } /** * The port number the server is listening on */ get port(): number | undefined { const address = this.server?.address(); if (typeof address === "object" && address !== null) { return address?.port; } return this.serverOptions?.port; } /** * The address the server is listening on */ get address(): string | undefined { const addressResult = this.server?.address(); // deno-coverage-ignore-start if (typeof addressResult === "object") { const address = addressResult?.address; if (address === "::") { return "localhost"; } if (address?.includes(":")) { return `[${address}]`; } return address; } return addressResult; } // deno-coverage-ignore-stop }