Compare commits

..
20 Commits
Author SHA1 Message Date
Dave Horton f3fe46319d update siprec client with fix for stop recording 2023-02-17 12:10:14 -05:00
Dave Horton 43bfeb439a update siprec-client with fix for smart tap xml 2023-02-14 14:15:11 -05:00
Dave Horton 31f34fbffa update to latest siprec client 2023-02-13 16:50:07 -05:00
Dave Horton 52d0670b88 bump version 2023-02-13 09:15:05 -05:00
Snyk bot f42128765d fix: Dockerfile to reduce vulnerabilities (#75)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3314623
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3314624
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3314624
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3314641
- https://snyk.io/vuln/SNYK-ALPINE316-OPENSSL-3314643
2023-02-12 12:45:19 -05:00
Dave Horton eac1d7a9e9 K8s scale in (#73)
* changes for proper scale-in for K8S

* fix check for call count
2023-02-07 19:58:01 -05:00
Dave Horton fae1732ddf update to latest db-helpers 2023-02-07 13:31:48 -05:00
Dave Horton c858624815 Feature/tcp to fs (#72)
* add env var K8S_FEATURE_SERVER_TRANSPORT

* add Contact with private address when using tcp to FS on K8S

* further refinement
2023-01-26 13:33:24 -05:00
Dave Horton 2f137f2bfc bugfix: handle calls with no user in To header 2023-01-22 18:03:12 -05:00
Dave Horton ef0dcfc021 update to rtpengine-utils with fix for not discarding dtmf as dups 2023-01-12 13:09:15 -05:00
Dave Horton fb8baa34af always enable dtmf from rtpengine, since dtmfCapture on FS now uses this rather than freeswitch dtmf events (#70) 2023-01-12 08:45:39 -05:00
Dave Horton 7efce18a03 gh: run tests on PR 2023-01-09 10:13:25 -05:00
Dave Horton 84e5202607 bugfix: in EC2 deployment restrict udp localport for rtpengine 2022-12-30 08:54:33 -05:00
Dave Horton 8f856a30a6 update to drachtio-srf@4.5.21 with some perf fixes 2022-12-29 09:51:14 -05:00
Dave Horton d9881632c2 faster uuid 2022-12-28 10:06:31 -06:00
Dave Horton 6d2b1a94e9 bugfix: proper detection of reinvite from FS to release media 2022-12-27 13:40:56 -06:00
Dave Horton ded83ac39a bump version 2022-12-24 12:06:57 -06:00
Dave Horton 91a29d2b2c bump siprec-utils 2022-12-21 11:44:37 -05:00
Dave Horton 27686a80e8 update to latest rtpengine-utils and drachtio-server 2022-12-21 11:20:47 -05:00
Dave Horton a9e79b23bd bugfix: account returned when carrier default routing is used was wrong 2022-12-19 21:09:14 -05:00
10 changed files with 3029 additions and 588 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Build image
run: docker build . --file Dockerfile --tag $IMAGE_NAME
+3 -5
View File
@@ -1,15 +1,13 @@
name: CI
on:
push:
workflow_dispatch:
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18.x
- run: npm ci
+1 -1
View File
@@ -1,4 +1,4 @@
FROM --platform=linux/amd64 node:18.12.1-alpine3.16 as base
FROM --platform=linux/amd64 node:18-alpine3.16 as base
RUN apk --update --no-cache add --virtual .builds-deps build-base python3
+30 -3
View File
@@ -28,6 +28,7 @@ const {
commitInterval: 'test' === process.env.NODE_ENV ? 7 : 20
});
const StatsCollector = require('@jambonz/stats-collector');
const CIDRMatcher = require('cidr-matcher');
const stats = new StatsCollector(logger);
const {equalsIgnoreOrder, createHealthCheckApp, systemHealth} = require('./lib/utils');
const {LifeCycleEvents} = require('./lib/constants');
@@ -129,7 +130,6 @@ const {
const CallSession = require('./lib/call-session');
if (process.env.DRACHTIO_HOST && !process.env.K8S) {
const CIDRMatcher = require('cidr-matcher');
const cidrs = process.env.JAMBONES_NETWORK_CIDR
.split(',')
.map((s) => s.trim());
@@ -164,6 +164,23 @@ else {
logger.info(`listening in outbound mode on port ${process.env.DRACHTIO_PORT}`);
});
srf.listen({port: process.env.DRACHTIO_PORT, secret: process.env.DRACHTIO_SECRET});
srf.on('connect', (err, hp) => {
if (err) return this.logger.error({err}, 'Error connecting to drachtio server');
logger.info(`connected to drachtio listening on ${hp}`);
if (process.env.K8S_FEATURE_SERVER_TRANSPORT === 'tcp') {
const matcher = new CIDRMatcher(['192.168.0.0/24', '172.16.0.0/16', '10.0.0.0/8']);
const hostports = hp.split(',');
for (const hp of hostports) {
const arr = /^(.*)\/(.*):(\d+)$/.exec(hp);
if (arr && matcher.contains(arr[2])) {
const hostport = `${arr[2]}:${arr[3]}`;
logger.info(`using sbc private address when sending to feature-server: ${hostport}`);
srf.locals.privateSipAddress = hostport;
}
}
}
});
}
if (process.env.NODE_ENV === 'test') {
srf.on('error', (err) => {
@@ -304,8 +321,18 @@ process.on('SIGUSR2', handle.bind(null, removeFromSet, setName));
process.on('SIGTERM', handle.bind(null, removeFromSet, setName));
function handle(removeFromSet, setName, signal) {
logger.info(`got signal ${signal}, removing ${srf.locals.privateSipAddress} from set ${setName}`);
removeFromSet(setName, srf.locals.privateSipAddress);
logger.info(`got signal ${signal}`);
if (srf.locals.privateSipAddress && setName) {
logger.info(`removing ${srf.locals.privateSipAddress} from set ${setName}`);
removeFromSet(setName, srf.locals.privateSipAddress);
}
if (process.env.K8S) {
lifecycleEmitter.operationalState = LifeCycleEvents.ScaleIn;
if (0 === activeCallIds.size) {
logger.info('exiting immediately since we have no calls in progress');
process.exit(0);
}
}
}
module.exports = {srf, logger};
+3
View File
@@ -57,6 +57,9 @@ module.exports = (logger) => {
}
})();
}
else if (process.env.K8S) {
lifecycleEmitter.scaleIn = () => process.exit(0);
}
return {lifecycleEmitter};
};
+5 -9
View File
@@ -85,10 +85,6 @@ class CallSession extends Emitter {
return this.req.has('X-Five9-StreamingPairId');
}
get isPossibleWebRtcClient() {
return this.req.locals.isPossibleWebRtcClient;
}
subscribeForDTMF(dlg) {
if (!this._subscribedForDTMF) {
this._subscribedForDTMF = true;
@@ -312,7 +308,7 @@ class CallSession extends Emitter {
_setDlgHandlers(dlg) {
const {callId} = dlg.sip;
this.activeCallIds.set(callId, this);
if (this.isPossibleWebRtcClient) this.subscribeForDTMF(dlg);
this.subscribeForDTMF(this.uac);
dlg.on('destroy', () => {
debug('call ended with normal termination');
this.logger.info('call ended with normal termination');
@@ -335,11 +331,11 @@ class CallSession extends Emitter {
_setHandlers({uas, uac}) {
this.emit('connected');
const callStart = Date.now();
const call_sid = uac.res?.get('X-Call-Sid');
const application_sid = this.application_sid || uac.res?.get('X-Application-Sid');
const tags = ['accepted:yes', 'sipStatus:200', `originator:${this.req.locals.originator}`];
this.stats.increment('sbc.terminations', tags);
this.activeCallIds.set(this.req.get('Call-ID'), this);
const call_sid = uac.res?.get('X-Call-Sid');
const application_sid = this.application_sid || uac.res?.get('X-Application-Sid');
if (this.req.locals.cdr) {
this.req.locals.cdr = {
...this.req.locals.cdr,
@@ -417,7 +413,7 @@ class CallSession extends Emitter {
});
});
if (this.isPossibleWebRtcClient) this.subscribeForDTMF(uac);
this.subscribeForDTMF(uac);
uas.on('modify', this._onReinvite.bind(this, uas));
uac.on('modify', this._onReinvite.bind(this, uac));
@@ -544,7 +540,7 @@ Duration=${payload.duration} `
req.body;
const reason = req.get('X-Reason');
const isReleasingMedia = reason && dlg.type === 'uas' && ['release-media', 'anchor-media'].includes(reason);
const isReleasingMedia = reason && dlg.type === 'uac' && ['release-media', 'anchor-media'].includes(reason);
const fromTag = dlg.type === 'uas' ? this.rtpEngineOpts.uas.tag : this.rtpEngineOpts.uac.tag;
const toTag = dlg.type === 'uas' ? this.rtpEngineOpts.uac.tag : this.rtpEngineOpts.uas.tag;
const offerMedia = dlg.type === 'uas' ? this.rtpEngineOpts.uac.mediaOpts : this.rtpEngineOpts.uas.mediaOpts;
+5 -3
View File
@@ -100,7 +100,7 @@ module.exports = (srf, logger) => {
};
const getApplicationForDidAndCarrier = async(req, voip_carrier_sid) => {
const did = normalizeDID(req.calledNumber);
const did = normalizeDID(req.calledNumber) || 'anonymous';
try {
/* straight DID match */
@@ -214,7 +214,7 @@ module.exports = (srf, logger) => {
if (matches.length) {
/* we have one or more matches. Now check for one with a provisioned phone number matching the DID */
const vc_sids = matches.map((m) => `'${m.voip_carrier_sid}'`).join(',');
const did = normalizeDID(req.calledNumber);
const did = normalizeDID(req.calledNumber) || 'anonymous';
const sql = `SELECT * FROM phone_numbers WHERE number = '${did}' AND voip_carrier_sid IN (${vc_sids})`;
logger.debug({matches, sql, did, vc_sids}, 'looking up DID');
@@ -233,13 +233,15 @@ module.exports = (srf, logger) => {
};
}
else if (accountLevelGateways.length === 1) {
const [accounts] = await pp.query('SELECT * from accounts where account_sid = ?',
accountLevelGateways[0].account_sid);
return {
fromCarrier: true,
gateway: accountLevelGateways[0],
service_provider_sid: accountLevelGateways[0].service_provider_sid,
account_sid: accountLevelGateways[0].account_sid,
application_sid: accountLevelGateways[0].application_sid,
account: accountLevelGateways[0]
account: accounts[0]
};
}
else {
+3 -1
View File
@@ -15,7 +15,9 @@ module.exports = (srf, logger) => {
return async() => {
try {
if (process.env.K8S) {
return process.env.K8S_FEATURE_SERVER_SERVICE_NAME;
return process.env.K8S_FEATURE_SERVER_TRANSPORT ?
`${process.env.K8S_FEATURE_SERVER_SERVICE_NAME};transport=${process.env.K8S_FEATURE_SERVER_TRANSPORT}` :
process.env.K8S_FEATURE_SERVER_SERVICE_NAME;
}
else {
const fs = await retrieveSet(setName);
+2972 -557
View File
File diff suppressed because it is too large Load Diff
+6 -8
View File
@@ -1,6 +1,6 @@
{
"name": "sbc-inbound",
"version": "v0.7.7",
"version": "v0.8.0",
"main": "app.js",
"engines": {
"node": ">= 12.0.0"
@@ -25,12 +25,12 @@
"jslint": "eslint app.js lib"
},
"dependencies": {
"@jambonz/db-helpers": "^0.7.3",
"@jambonz/db-helpers": "^0.7.4",
"@jambonz/http-authenticator": "^0.2.2",
"@jambonz/http-health-check": "^0.0.1",
"@jambonz/realtimedb-helpers": "^0.5.7",
"@jambonz/rtpengine-utils": "^0.3.11",
"@jambonz/siprec-client-utils": "^0.1.4",
"@jambonz/realtimedb-helpers": "^0.6.3",
"@jambonz/rtpengine-utils": "^0.4.3",
"@jambonz/siprec-client-utils": "^0.2.4",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.2.5",
"aws-sdk": "^2.1261.0",
@@ -38,11 +38,9 @@
"cidr-matcher": "^2.1.1",
"debug": "^4.3.4",
"drachtio-fn-b2b-sugar": "0.0.12",
"drachtio-srf": "^4.5.2",
"drachtio-srf": "^4.5.21",
"express": "^4.18.1",
"pino": "^7.11.0",
"sdp-transform": "^2.14.1",
"uuid": "^8.3.2",
"verify-aws-sns-signature": "^0.1.0",
"xml2js": "^0.4.23"
},