First commit merge

This commit is contained in:
kbe
2025-10-09 16:37:02 +02:00
parent 915ef14fc5
commit 5aae456ab3
20 changed files with 2584 additions and 2 deletions

View File

@@ -0,0 +1,142 @@
const logger = require('../utils/logger');
const RequestValidator = require('./validation');
const UserAgentFilter = require('./userAgentFilter');
/**
* Request Processing Pipeline - Equivalent to Kamailio's main request_route
* This is the primary entry point for all SIP requests received by Drachtio
*/
class RequestProcessor {
constructor(srf) {
this.srf = srf;
this.validator = new RequestValidator();
this.uaFilter = new UserAgentFilter();
}
/**
* Handle OPTIONS requests (equivalent to kamailio.cfg:297-301)
*/
handleOptions(req, res) {
logger.info('[OPTIONS] Options request from %s:%s | Call-ID: %s',
req.source_address, req.source_port, req.get('Call-ID'));
res.send(200, 'OK');
}
/**
* Handle CANCEL requests (equivalent to kamailio.cfg:196-201)
*/
handleCancel(req, res) {
const callId = req.get('Call-ID');
logger.info('[CANCEL] CANCEL: Call-ID: %s', callId);
// Check if transaction exists
if (this.srf.hasUacTransaction(callId)) {
// Relay the CANCEL to the appropriate destination
this.srf.createUacRequest('CANCEL', req.uri, {
headers: {
'Call-ID': callId,
'CSeq': req.get('CSeq'),
'From': req.get('From'),
'To': req.get('To'),
'Via': req.get('Via'),
'Route': req.get('Route'),
'Max-Forwards': req.get('Max-Forwards')
}
})
.then(() => {
res.send(200, 'OK');
})
.catch((err) => {
logger.error('[CANCEL] Failed to relay CANCEL: %s', err.message);
res.send(500, 'Server Error');
});
} else {
res.send(481, 'Transaction Does Not Exist');
}
}
/**
* Handle in-dialog requests (equivalent to kamailio.cfg:239-241)
*/
handleInDialog(req, res, next) {
if (req.has('To') && req.getParsedHeader('to').params.tag && req.method !== 'INVITE') {
logger.info('[WITHINDLG] %s request | Call-ID: %s', req.method, req.get('Call-ID'));
// Pass to in-dialog handler
next();
} else {
next();
}
}
/**
* Handle presence-related requests (equivalent to kamailio.cfg:304)
*/
handlePresence(req, res) {
if (req.method === 'PUBLISH' || req.method === 'SUBSCRIBE') {
logger.info('[PRESENCE] %s request from %s:%s | Call-ID: %s',
req.method, req.source_address, req.source_port, req.get('Call-ID'));
res.send(404, 'Not here');
return true;
}
return false;
}
/**
* Handle requests that don't match specific routes (equivalent to kamailio.cfg:312-315)
*/
handleUnmatchedRequest(req, res) {
logger.warn('[MAIN_ROUTE] No specific route found for method: %s to %s | Call-ID: %s',
req.method, req.uri.user, req.get('Call-ID'));
res.send(501, 'Not Implemented - No action found for destination or method');
}
/**
* Main request processing pipeline
*/
processRequest() {
return (req, res, next) => {
logger.debug('[REQUEST_PROCESSOR] Processing %s request from %s:%s',
req.method, req.source_address, req.source_port);
// Apply validation middleware
this.validator.middleware()(req, res, () => {
// Apply User-Agent filtering
this.uaFilter.middleware()(req, res, () => {
// Handle specific method types
switch (req.method) {
case 'OPTIONS':
this.handleOptions(req, res);
break;
case 'CANCEL':
this.handleCancel(req, res);
break;
case 'REGISTER':
// Pass to registration handler
next();
break;
case 'INVITE':
// Pass to INVITE handler
next();
break;
default:
// Handle in-dialog requests
this.handleInDialog(req, res, () => {
// Check for presence requests
if (!this.handlePresence(req, res)) {
// If no specific handler, return error
this.handleUnmatchedRequest(req, res);
}
});
break;
}
});
});
};
}
}
module.exports = RequestProcessor;