UNPKG

osc-mcp-server

Version:

Model Context Protocol server for OSC (Open Sound Control) endpoint management

170 lines 5.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OSCEndpoint = void 0; exports.createOSCEndpoint = createOSCEndpoint; const dgram_1 = require("dgram"); const events_1 = require("events"); const index_1 = require("../types/index"); const parser_1 = require("./parser"); const buffer_1 = require("./buffer"); const index_2 = require("../errors/index"); class OSCEndpoint extends events_1.EventEmitter { id; port; bufferSize; addressFilters; createdAt; socket = null; status = 'stopped'; messageBuffer; messageCount = 0; constructor(id, config) { super(); this.id = id; this.port = config.port; this.bufferSize = config.bufferSize || 1000; this.addressFilters = config.addressFilters || []; this.createdAt = new Date(); if (!this.isValidPort(this.port)) { const error = index_2.NetworkErrors.portInvalid(this.port); throw new Error(error.message); } const bufferConfig = { maxSize: this.bufferSize, addressFilters: this.addressFilters, }; this.messageBuffer = (0, buffer_1.createMessageBuffer)(bufferConfig); } async startListening() { if (this.status === 'active') { const error = index_2.EndpointErrors.alreadyActive(this.id); throw new Error(error.message); } return new Promise((resolve, reject) => { try { this.socket = (0, dgram_1.createSocket)('udp4'); this.socket.on('error', (error) => { this.handleSocketError(error); reject(error); }); this.socket.on('message', (data, rinfo) => { this.handleIncomingMessage(data, rinfo); }); this.socket.bind(this.port, () => { this.status = 'active'; this.emit('statusChange', this.status); resolve(); }); } catch (error) { this.status = 'error'; this.emit('statusChange', this.status); const startError = index_2.EndpointErrors.startFailed(this.id, error instanceof Error ? error.message : 'Unknown error'); reject(new Error(startError.message)); } }); } async stopListening() { if (this.status === 'stopped') { return; } return new Promise(resolve => { if (this.socket) { this.socket.close(() => { this.socket = null; this.status = 'stopped'; this.emit('statusChange', this.status); resolve(); }); } else { this.status = 'stopped'; this.emit('statusChange', this.status); resolve(); } }); } getStatus() { return { id: this.id, port: this.port, status: this.status, bufferSize: this.bufferSize, addressFilters: [...this.addressFilters], createdAt: this.createdAt, messageCount: this.messageCount, }; } getMessageBuffer() { return this.messageBuffer; } getId() { return this.id; } getPort() { return this.port; } isActive() { return this.status === 'active'; } handleIncomingMessage(data, rinfo) { try { const parseResult = (0, parser_1.parseOSCMessage)(data, rinfo.address, rinfo.port); if (parseResult.error) { this.emit('error', parseResult.error); return; } if (parseResult.message) { this.messageBuffer.addMessage(parseResult.message); this.messageCount++; this.emit('message', parseResult.message); } } catch (error) { const oscError = { code: index_1.ErrorCode.MESSAGE_PARSE_ERROR, message: `Unexpected error processing message: ${error instanceof Error ? error.message : 'Unknown error'}`, details: { originalError: error }, }; this.emit('error', oscError); } } handleSocketError(error) { this.status = 'error'; this.emit('statusChange', this.status); let oscError; if (error.message.includes('EADDRINUSE')) { oscError = index_2.NetworkErrors.portInUse(this.port, this.getSuggestedPorts()); } else if (error.message.includes('EACCES')) { oscError = index_2.NetworkErrors.permissionDenied(this.port); } else { oscError = index_2.NetworkErrors.networkError(`Network error on endpoint ${this.id}: ${error.message}`, { originalError: error, port: this.port, endpointId: this.id, }); } this.emit('error', oscError); } isValidPort(port) { return Number.isInteger(port) && port >= 1024 && port <= 65535; } getSuggestedPorts() { const suggestions = []; const basePort = this.port; for (let i = 1; i <= 3; i++) { const suggestedPort = basePort + i; if (suggestedPort <= 65535) { suggestions.push(suggestedPort); } } return suggestions; } } exports.OSCEndpoint = OSCEndpoint; function createOSCEndpoint(id, config) { return new OSCEndpoint(id, config); } //# sourceMappingURL=endpoint.js.map