Compare commits

...
18 Commits
Author SHA1 Message Date
Dave Horton 7382bf6bd6 bump version 2022-04-06 08:18:08 -04:00
Dave Horton abfce38150 logging 2022-04-01 15:12:44 -04:00
Dave Horton d8035c978e bugfix: error writing call counts 2022-04-01 15:09:46 -04:00
Dave Horton 91cd677ad8 write call_counts time series data tracking inbound call counts by account 2022-04-01 13:08:25 -04:00
Dave Horton 17b53438e2 track account level calls if env JAMBONES_TRACK_ACCOUNT_CALLS is set 2022-04-01 06:51:44 -04:00
Dave Horton f1e2f192b7 Bugfix/mem leak (#29)
* wait for 200 OK to BYE before closing connection to drachtio

* minor logging
2022-03-27 21:50:09 -04:00
Dave Horton 0af8bcc348 remove dlg event handlers on destroy 2022-03-27 20:23:30 -04:00
Dave Horton e067125974 de-link Dialogs so they can be GC'ed at call end 2022-03-27 19:43:39 -04:00
Dave Horton 2dadde64f4 write otel trace_id to call history 2022-03-23 09:29:22 -04:00
Dave Horton d5a1337811 bugfix: connection to drachtio was not closed on non-success response to invite (#27) 2022-03-18 14:04:52 -04:00
Snyk bot a6571134cd fix: Dockerfile to reduce vulnerabilities (#26)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-DEBIAN11-GNUTLS28-2419151
- https://snyk.io/vuln/SNYK-DEBIAN11-OPENSSL-2388380
- https://snyk.io/vuln/SNYK-DEBIAN11-OPENSSL-2426309
- https://snyk.io/vuln/SNYK-DEBIAN11-UTILLINUX-2401081
- https://snyk.io/vuln/SNYK-DEBIAN11-UTILLINUX-2401081
2022-03-18 07:54:19 -04:00
Dave Horton e0e5c75496 bump version 2022-03-08 20:15:17 -05:00
Dave Horton c08e35c261 Feature/incoming refer (#25)
* handle incoming REFER and send on to the FS

* clarity
2022-03-05 15:22:11 -05:00
Dave Horton 883c63723c update to dbhelpers with support for searching root domains to identify account 2022-02-17 20:59:17 -05:00
Dave Horton 13f78bf8d9 added pre-commit hook for linting 2022-02-14 13:18:04 -05:00
Dave Horton 55056c1771 bump version 2022-02-09 15:43:40 -05:00
Dave Horton 87ec5f8e09 update to latest @jambonz/realtimedb-helpers with support for redis username / password auth 2022-02-09 15:13:54 -05:00
Dave Horton 317280befc update deps 2022-02-09 08:22:14 -05:00
8 changed files with 1995 additions and 272 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"jsx": false,
"modules": false
},
"ecmaVersion": 2018
"ecmaVersion": 2020
},
"plugins": ["promise"],
"rules": {
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run jslint
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:17.4-slim
FROM node:17-slim
WORKDIR /opt/app/
COPY package.json ./
RUN npm install
+2
View File
@@ -14,6 +14,7 @@ const opts = Object.assign({
}, {level: process.env.JAMBONES_LOGLEVEL || 'info'});
const logger = require('pino')(opts);
const {
writeCallCount,
queryCdrs,
writeCdrs,
writeAlerts,
@@ -61,6 +62,7 @@ const {getRtpEngine, setRtpEngines} = require('@jambonz/rtpengine-utils')([], lo
});
srf.locals = {...srf.locals,
stats,
writeCallCount,
queryCdrs,
writeCdrs,
writeAlerts,
+38 -11
View File
@@ -171,7 +171,7 @@ class CallSession extends Emitter {
'-Session-Expires',
'-X-Subspace-Forwarded-For'
],
proxyResponseHeaders: ['all'],
proxyResponseHeaders: ['all', '-X-Trace-ID'],
localSdpB: response.sdp,
localSdpA: async(sdp, res) => {
this.rtpEngineOpts.uac.tag = res.getParsedHeader('To').params.tag;
@@ -204,7 +204,7 @@ class CallSession extends Emitter {
const tags = ['accepted:no', `sipStatus:${err.status}`, `originator:${this.req.locals.originator}`];
this.stats.increment('sbc.terminations', tags);
this.logger.info(`call failed to connect to feature server with ${err.status}`);
return this.emit('failed');
this.emit('failed');
}
else if (err.message !== 'call canceled') {
this.logger.error(err, 'unexpected error routing inbound call');
@@ -241,22 +241,30 @@ class CallSession extends Emitter {
this.req.locals.cdr = {
...this.req.locals.cdr,
answered: true,
answered_at: callStart
answered_at: callStart,
trace_id: uac.res?.get('X-Trace-ID') || '00000000000000000000000000000000'
};
}
this.uas = uas;
this.uac = uac;
[uas, uac].forEach((dlg) => {
dlg.on('destroy', () => {
this.logger.info('call ended with normal termination');
dlg.on('destroy', async() => {
const other = dlg.other;
this.rtpEngineResource.destroy().catch((err) => {});
this.activeCallIds.delete(this.req.get('Call-ID'));
dlg.other.destroy().catch((e) => {});
try {
await other.destroy();
} catch (err) {}
this.unsubscribeDTMF(this.logger, this.req.get('Call-ID'), this.rtpEngineOpts.uas.tag);
if (process.env.JAMBONES_HOSTING) {
if (process.env.JAMBONES_HOSTING || process.env.JAMBONES_TRACK_ACCOUNT_CALLS) {
const {account_sid} = this.req.locals;
this.decrKey(this.callCountKey)
.then((count) => this.logger.debug({key: this.callCountKey},
`after hangup there are ${count} active calls for this account`))
.then((count) => {
this.logger.info(
{key: this.callCountKey},
`after hangup there are ${count} active calls for this account`);
return this.req.srf.locals.writeCallCount({account_sid, calls_in_progress: count});
})
.catch((err) => this.logger.error({err}, 'Error decrementing call count'));
}
@@ -274,6 +282,13 @@ class CallSession extends Emitter {
trunk
}).catch((err) => this.logger.error({err}, 'Error writing cdr for completed call'));
}
/* de-link the 2 Dialogs for GC */
dlg.removeAllListeners();
other.removeAllListeners();
dlg.other = null;
other.other = null;
this.logger.info(`call ended with normal termination, there are ${this.activeCallIds.size} active`);
this.srf.endSession(this.req);
});
});
@@ -618,8 +633,20 @@ Duration=${payload.duration} `
}
}
else {
// TODO: forward on to feature server
res.send(501);
/* REFER coming in from a sip device, forward to feature server */
try {
const response = await dlg.other.request({
method: 'REFER',
headers: {
'Refer-To': req.get('Refer-To'),
'Referred-By': req.get('Referred-By'),
'User-Agent': req.get('User-Agent')
}
});
res.send(response.status, response.reason);
} catch (err) {
this.logger.error({err}, 'CallSession:_onRefer: error handling incoming REFER');
}
}
}
+9 -4
View File
@@ -220,11 +220,11 @@ module.exports = function(srf, logger) {
};
const checkLimits = async(req, res, next) => {
if (!process.env.JAMBONES_HOSTING) return next(); // skip
if (!process.env.JAMBONES_HOSTING && !process.env.JAMBONES_TRACK_ACCOUNT_CALLS) return next(); // skip
const {incrKey, decrKey} = req.srf.locals.realtimeDbHelpers;
const {logger, account_sid} = req.locals;
const {writeAlerts, AlertType} = req.srf.locals;
const {writeCallCount, writeAlerts, AlertType} = req.srf.locals;
assert(account_sid);
const key = makeCallCountKey(account_sid);
@@ -233,10 +233,11 @@ module.exports = function(srf, logger) {
if (status > 200) {
decrKey(key)
.then((count) => {
logger.debug({key}, `after rejection there are ${count} active calls for this account`);
logger.info({key}, `after rejection there are ${count} active calls for this account`);
debug({key}, `after rejection there are ${count} active calls for this account`);
return;
return count;
})
.then((count) => writeCallCount({account_sid, calls_in_progress: count}))
.catch((err) => logger.error({err}, 'checkLimits: decrKey err'));
}
});
@@ -244,6 +245,10 @@ module.exports = function(srf, logger) {
try {
/* increment the call count */
const calls = await incrKey(key);
writeCallCount({account_sid, calls_in_progress: calls})
.then(() => logger.info(`checkLimits: after incrementing there are ${calls} active calls for this account`))
.catch((err) => logger.error({err}, 'checkLimits: error writing call count'));
if (!process.env.JAMBONES_HOSTING) return next();
/* compare to account's limit, though avoid db hit when call count is low */
const minLimit = process.env.MIN_CALL_LIMIT ?
+1934 -250
View File
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -1,6 +1,6 @@
{
"name": "sbc-inbound",
"version": "v0.7.2",
"version": "v0.7.5",
"main": "app.js",
"engines": {
"node": ">= 12.0.0"
@@ -25,13 +25,13 @@
"jslint": "eslint app.js lib"
},
"dependencies": {
"@jambonz/db-helpers": "^0.6.16",
"@jambonz/db-helpers": "^0.6.17",
"@jambonz/http-authenticator": "^0.2.0",
"@jambonz/http-health-check": "^0.0.1",
"@jambonz/realtimedb-helpers": "^0.4.9",
"@jambonz/rtpengine-utils": "^0.3.0-beta.3",
"@jambonz/realtimedb-helpers": "^0.4.24",
"@jambonz/rtpengine-utils": "^0.3.1",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.1.6",
"@jambonz/time-series": "^0.1.9",
"aws-sdk": "^2.1036.0",
"bent": "^7.3.12",
"cidr-matcher": "^2.1.1",
@@ -39,6 +39,7 @@
"drachtio-fn-b2b-sugar": "0.0.12",
"drachtio-srf": "^4.4.59",
"express": "^4.17.1",
"husky": "^7.0.4",
"pino": "^7.4.1",
"rtpengine-client": "^0.2.0",
"verify-aws-sns-signature": "^0.0.6",