const config = require('config'); const logger = require('./utils/logger'); const { Srf } = require('drachtio-srf'); const RequestProcessor = require('./middleware/requestProcessor'); const RegistrationHandler = require('./routes/registration'); const InviteHandler = require('./routes/invite'); const InDialogHandler = require('./routes/indialog'); /** * NexusVoice SIP Border Controller - Drachtio Implementation * * This server provides equivalent functionality to the Kamailio configuration: * - SIP request validation and security filtering * - User registration and location management * - Call routing and media handling * - Integration with external systems (Asterisk, RTP proxy) */ class SipServer { constructor() { this.srf = new Srf(); this.config = config; this.requestProcessor = new RequestProcessor(this.srf); this.registrationHandler = new RegistrationHandler(this.srf); this.inviteHandler = new InviteHandler(this.srf); this.inDialogHandler = new InDialogHandler(this.srf); } /** * Initialize the SIP server */ async initialize() { try { logger.info('Initializing NexusVoice SBC...'); // Configure SIP listening parameters const sipConfig = this.config.get('sip'); // Connect to drachtio server await this.srf.connect({ host: sipConfig.host, port: sipConfig.port, transport: sipConfig.transport }); logger.info('Connected to drachtio server on %s:%s', sipConfig.host, sipConfig.port); // Setup middleware pipeline (equivalent to Kamailio's request_route) this.setupMiddleware(); // Setup method-specific handlers this.setupMethodHandlers(); // Setup in-dialog handlers this.setupInDialogHandlers(); logger.info('NexusVoice SBC initialized successfully'); } catch (error) { logger.error('Failed to initialize SBC: %s', error.message); throw error; } } /** * Setup the main request processing pipeline */ setupMiddleware() { logger.info('Setting up request processing pipeline...'); // Apply the main request processor middleware this.srf.use(this.requestProcessor.processRequest()); logger.info('Request processing pipeline configured'); } /** * Setup method-specific request handlers */ setupMethodHandlers() { logger.info('Setting up method-specific handlers...'); // REGISTER requests (equivalent to kamailio.cfg:186-189) this.srf.register((req, res) => { this.registrationHandler.handleRegister(req, res); }); // INVITE requests (equivalent to kamailio.cfg:210-212) this.srf.invite((req, res) => { this.inviteHandler.handleInvite(req, res); }); logger.info('Method-specific handlers configured'); } /** * Setup in-dialog request handlers */ setupInDialogHandlers() { logger.info('Setting up in-dialog handlers...'); // Handle all in-dialog requests this.srf.dialog((req, res) => { this.inDialogHandler.handleInDialog(req, res); }); logger.info('In-dialog handlers configured'); } /** * Start the server */ async start() { try { await this.initialize(); logger.info('NexusVoice SBC started successfully'); } catch (error) { logger.error('Failed to start SBC: %s', error.message); process.exit(1); } } /** * Graceful shutdown */ async shutdown() { logger.info('Shutting down NexusVoice SBC...'); try { await this.srf.disconnect(); logger.info('NexusVoice SBC shutdown complete'); } catch (error) { logger.error('Error during shutdown: %s', error.message); } } } // Create and start the server instance const server = new SipServer(); // Handle graceful shutdown process.on('SIGTERM', async () => { await server.shutdown(); process.exit(0); }); process.on('SIGINT', async () => { await server.shutdown(); process.exit(0); }); // Start the server server.start().catch((error) => { logger.error('Failed to start server: %s', error.message); process.exit(1); }); module.exports = SipServer;