import dgram, { RemoteInfo } from 'dgram' import { UdpSocketCommunicator } from '../socket_communicator/udp_socket_communicator' import { OperationHandler } from '../operations_base/operation_handler' import { GeneralOperations } from '../operations_custom/general_operations' export class UdpServer { private readonly udpServer: dgram.Socket private readonly operationHandler: OperationHandler private readonly port: number private readonly host: string constructor(host: string, port: number) { this.udpServer = dgram.createSocket('udp4') this.operationHandler = OperationHandler.getInstance() this.host = host this.port = port // Load only the GeneralOperations into the operation handler this.operationHandler.loadPlugin(new GeneralOperations()) } // Unified logging function private log(message: string, level: 'log' | 'error' = 'log'): void { const prefix = '[UdpServer]' if (level === 'error') { console.error(`${prefix} ${message}`) } else { console.log(`${prefix} ${message}`) } } // Start the UDP server public start(): void { this.udpServer.on('message', this.handleUdpMessages.bind(this)) this.udpServer.on('error', this.handleError.bind(this)) this.udpServer.on('listening', this.handleListening.bind(this)) // Bind the server to the UDP port and host this.udpServer.bind(this.port, this.host) } // Handle incoming UDP messages private async handleUdpMessages(msg: Buffer, rinfo: RemoteInfo): Promise { const ip = rinfo.address const port = rinfo.port this.log(`Received message from ${ip}:${port}`) // Create a temporary communicator for the incoming message const communicator = new UdpSocketCommunicator(this.udpServer, ip, port, this.operationHandler) // Process the incoming message using the communicator await communicator.handleIncomingMessage(msg.toString()) const communicatorResult = communicator.getHandlerResult() if (communicatorResult) { // Send response back to the client using the temporary communicator try { await communicator.sendMessage( communicatorResult.operationCode, communicatorResult.metaInfo, ) this.log(`Sent response to ${ip}:${port}`) } catch (error: any) { this.log(`Error sending response to ${ip}:${port}: ${error.message}`, 'error') } } } // Handle UDP server errors private handleError(err: Error): void { this.log(`UDP server error:\n${err.stack}`, 'error') } // Handle when the UDP server starts listening private handleListening(): void { const address = this.udpServer.address() this.log(`UDP server listening on ${address.address}:${address.port}`) } }