import * as plugins from './smartvpn.plugins.js'; import { VpnBridge } from './smartvpn.classes.vpnbridge.js'; import type { IVpnServerOptions, IVpnServerConfig, IVpnStatus, IVpnServerStatistics, IVpnClientInfo, IVpnKeypair, TVpnServerCommands, } from './smartvpn.interfaces.js'; /** * VPN Server — manages a smartvpn daemon in server mode. */ export class VpnServer extends plugins.events.EventEmitter { private bridge: VpnBridge; private options: IVpnServerOptions; constructor(options: IVpnServerOptions) { super(); this.options = options; this.bridge = new VpnBridge({ transport: options.transport, mode: 'server', }); // Forward bridge events this.bridge.on('exit', (code: number | null, signal: string | null) => { this.emit('exit', { code, signal }); }); this.bridge.on('reconnected', () => { this.emit('reconnected'); }); } /** * Start the daemon bridge (spawn or connect). */ public async start(config?: IVpnServerConfig): Promise { const started = await this.bridge.start(); if (!started) { throw new Error('VpnServer: failed to start daemon bridge'); } const cfg = config || this.options.config; if (cfg) { await this.bridge.sendCommand('start', { config: cfg }); } } /** * Stop the VPN server. */ public async stopServer(): Promise { await this.bridge.sendCommand('stop', {} as Record); } /** * Get server status. */ public async getStatus(): Promise { return this.bridge.sendCommand('getStatus', {} as Record); } /** * Get server statistics. */ public async getStatistics(): Promise { return this.bridge.sendCommand('getStatistics', {} as Record); } /** * List connected clients. */ public async listClients(): Promise { const result = await this.bridge.sendCommand('listClients', {} as Record); return result.clients; } /** * Disconnect a specific client. */ public async disconnectClient(clientId: string): Promise { await this.bridge.sendCommand('disconnectClient', { clientId }); } /** * Generate a new Noise keypair. */ public async generateKeypair(): Promise { return this.bridge.sendCommand('generateKeypair', {} as Record); } /** * Stop the daemon bridge. */ public stop(): void { this.bridge.stop(); } /** * Whether the bridge is running. */ public get running(): boolean { return this.bridge.running; } }