Files
smartvpn/ts/smartvpn.classes.vpnserver.ts

108 lines
2.6 KiB
TypeScript
Raw Normal View History

2026-02-27 10:18:23 +00:00
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<TVpnServerCommands>;
private options: IVpnServerOptions;
constructor(options: IVpnServerOptions) {
super();
this.options = options;
this.bridge = new VpnBridge<TVpnServerCommands>({
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<void> {
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<void> {
await this.bridge.sendCommand('stop', {} as Record<string, never>);
}
/**
* Get server status.
*/
public async getStatus(): Promise<IVpnStatus> {
return this.bridge.sendCommand('getStatus', {} as Record<string, never>);
}
/**
* Get server statistics.
*/
public async getStatistics(): Promise<IVpnServerStatistics> {
return this.bridge.sendCommand('getStatistics', {} as Record<string, never>);
}
/**
* List connected clients.
*/
public async listClients(): Promise<IVpnClientInfo[]> {
const result = await this.bridge.sendCommand('listClients', {} as Record<string, never>);
return result.clients;
}
/**
* Disconnect a specific client.
*/
public async disconnectClient(clientId: string): Promise<void> {
await this.bridge.sendCommand('disconnectClient', { clientId });
}
/**
* Generate a new Noise keypair.
*/
public async generateKeypair(): Promise<IVpnKeypair> {
return this.bridge.sendCommand('generateKeypair', {} as Record<string, never>);
}
/**
* Stop the daemon bridge.
*/
public stop(): void {
this.bridge.stop();
}
/**
* Whether the bridge is running.
*/
public get running(): boolean {
return this.bridge.running;
}
}