import * as plugins from '../../plugins.js'; import type { ICertificateData, ICertificateFailure, ICertificateExpiring } from '../models/common-types.js'; import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js'; import { Port80HandlerEvents } from '../models/common-types.js'; /** * Standardized event names used throughout the system */ export enum ProxyEvents { // Certificate events CERTIFICATE_ISSUED = 'certificate:issued', CERTIFICATE_RENEWED = 'certificate:renewed', CERTIFICATE_FAILED = 'certificate:failed', CERTIFICATE_EXPIRING = 'certificate:expiring', // Component lifecycle events COMPONENT_STARTED = 'component:started', COMPONENT_STOPPED = 'component:stopped', // Connection events CONNECTION_ESTABLISHED = 'connection:established', CONNECTION_CLOSED = 'connection:closed', CONNECTION_ERROR = 'connection:error', // Request events REQUEST_RECEIVED = 'request:received', REQUEST_COMPLETED = 'request:completed', REQUEST_ERROR = 'request:error', // Route events ROUTE_MATCHED = 'route:matched', ROUTE_UPDATED = 'route:updated', ROUTE_ERROR = 'route:error', // Security events SECURITY_BLOCKED = 'security:blocked', SECURITY_BREACH_ATTEMPT = 'security:breach-attempt', // TLS events TLS_HANDSHAKE_STARTED = 'tls:handshake-started', TLS_HANDSHAKE_COMPLETED = 'tls:handshake-completed', TLS_HANDSHAKE_FAILED = 'tls:handshake-failed' } /** * Component types for event metadata */ export enum ComponentType { SMART_PROXY = 'smart-proxy', NETWORK_PROXY = 'network-proxy', NFTABLES_PROXY = 'nftables-proxy', PORT80_HANDLER = 'port80-handler', CERTIFICATE_MANAGER = 'certificate-manager', ROUTE_MANAGER = 'route-manager', CONNECTION_MANAGER = 'connection-manager', TLS_MANAGER = 'tls-manager', SECURITY_MANAGER = 'security-manager' } /** * Base event data interface */ export interface IEventData { timestamp: number; componentType: ComponentType; componentId?: string; } /** * Certificate event data */ export interface ICertificateEventData extends IEventData, ICertificateData { isRenewal?: boolean; source?: string; } /** * Certificate failure event data */ export interface ICertificateFailureEventData extends IEventData, ICertificateFailure {} /** * Certificate expiring event data */ export interface ICertificateExpiringEventData extends IEventData, ICertificateExpiring {} /** * Component lifecycle event data */ export interface IComponentEventData extends IEventData { name: string; version?: string; } /** * Connection event data */ export interface IConnectionEventData extends IEventData { connectionId: string; clientIp: string; serverIp?: string; port: number; isTls?: boolean; domain?: string; } /** * Request event data */ export interface IRequestEventData extends IEventData { connectionId: string; requestId: string; method?: string; path?: string; statusCode?: number; duration?: number; routeId?: string; routeName?: string; } /** * Route event data */ export interface IRouteEventData extends IEventData { route: IRouteConfig; context?: any; } /** * Security event data */ export interface ISecurityEventData extends IEventData { clientIp: string; reason: string; routeId?: string; routeName?: string; } /** * TLS event data */ export interface ITlsEventData extends IEventData { connectionId: string; domain?: string; clientIp: string; tlsVersion?: string; cipherSuite?: string; sniHostname?: string; } /** * Logger interface for event system */ export interface IEventLogger { info: (message: string, ...args: any[]) => void; warn: (message: string, ...args: any[]) => void; error: (message: string, ...args: any[]) => void; debug?: (message: string, ...args: any[]) => void; } /** * Event handler type */ export type EventHandler = (data: T) => void; /** * Helper class to standardize event emission and handling * across all system components */ export class EventSystem { private emitter: plugins.EventEmitter; private componentType: ComponentType; private componentId: string; private logger?: IEventLogger; constructor( componentType: ComponentType, componentId: string = '', logger?: IEventLogger ) { this.emitter = new plugins.EventEmitter(); this.componentType = componentType; this.componentId = componentId; this.logger = logger; } /** * Emit a certificate issued event */ public emitCertificateIssued(data: Omit): void { const eventData: ICertificateEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.info?.(`Certificate issued for ${data.domain}`); this.emitter.emit(ProxyEvents.CERTIFICATE_ISSUED, eventData); } /** * Emit a certificate renewed event */ public emitCertificateRenewed(data: Omit): void { const eventData: ICertificateEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.info?.(`Certificate renewed for ${data.domain}`); this.emitter.emit(ProxyEvents.CERTIFICATE_RENEWED, eventData); } /** * Emit a certificate failed event */ public emitCertificateFailed(data: Omit): void { const eventData: ICertificateFailureEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.error?.(`Certificate issuance failed for ${data.domain}: ${data.error}`); this.emitter.emit(ProxyEvents.CERTIFICATE_FAILED, eventData); } /** * Emit a certificate expiring event */ public emitCertificateExpiring(data: Omit): void { const eventData: ICertificateExpiringEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.warn?.(`Certificate expiring for ${data.domain} in ${data.daysRemaining} days`); this.emitter.emit(ProxyEvents.CERTIFICATE_EXPIRING, eventData); } /** * Emit a component started event */ public emitComponentStarted(name: string, version?: string): void { const eventData: IComponentEventData = { name, version, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.info?.(`Component ${name} started${version ? ` (v${version})` : ''}`); this.emitter.emit(ProxyEvents.COMPONENT_STARTED, eventData); } /** * Emit a component stopped event */ public emitComponentStopped(name: string): void { const eventData: IComponentEventData = { name, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.info?.(`Component ${name} stopped`); this.emitter.emit(ProxyEvents.COMPONENT_STOPPED, eventData); } /** * Emit a connection established event */ public emitConnectionEstablished(data: Omit): void { const eventData: IConnectionEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.debug?.(`Connection ${data.connectionId} established from ${data.clientIp} on port ${data.port}`); this.emitter.emit(ProxyEvents.CONNECTION_ESTABLISHED, eventData); } /** * Emit a connection closed event */ public emitConnectionClosed(data: Omit): void { const eventData: IConnectionEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.debug?.(`Connection ${data.connectionId} closed`); this.emitter.emit(ProxyEvents.CONNECTION_CLOSED, eventData); } /** * Emit a route matched event */ public emitRouteMatched(data: Omit): void { const eventData: IRouteEventData = { ...data, timestamp: Date.now(), componentType: this.componentType, componentId: this.componentId }; this.logger?.debug?.(`Route matched: ${data.route.name || data.route.id || 'unnamed'}`); this.emitter.emit(ProxyEvents.ROUTE_MATCHED, eventData); } /** * Subscribe to an event */ public on(event: ProxyEvents, handler: EventHandler): void { this.emitter.on(event, handler); } /** * Subscribe to an event once */ public once(event: ProxyEvents, handler: EventHandler): void { this.emitter.once(event, handler); } /** * Unsubscribe from an event */ public off(event: ProxyEvents, handler: EventHandler): void { this.emitter.off(event, handler); } /** * Map Port80Handler events to standard proxy events */ public subscribePort80HandlerEvents(handler: any): void { handler.on(Port80HandlerEvents.CERTIFICATE_ISSUED, (data: ICertificateData) => { this.emitCertificateIssued({ ...data, isRenewal: false, source: 'port80handler' }); }); handler.on(Port80HandlerEvents.CERTIFICATE_RENEWED, (data: ICertificateData) => { this.emitCertificateRenewed({ ...data, isRenewal: true, source: 'port80handler' }); }); handler.on(Port80HandlerEvents.CERTIFICATE_FAILED, (data: ICertificateFailure) => { this.emitCertificateFailed(data); }); handler.on(Port80HandlerEvents.CERTIFICATE_EXPIRING, (data: ICertificateExpiring) => { this.emitCertificateExpiring(data); }); } }