Compare commits

...
25 Commits
Author SHA1 Message Date
Dave Horton e3963bf057 bugfix: re-invite handling from UAC side now handled properly 2021-04-27 08:16:36 -04:00
Dave Horton 238f3fe05a add test case for cidr matching of carrier inbound calls 2021-03-10 10:45:56 -05:00
Dave Horton 51e926629c update to db-helpers that supports sip gateways identified by cidr range 2021-03-09 19:00:35 -05:00
Dave Horton 3df94ced57 Merge pull request #8 from radicaldrew/master
Updated Dockerfile
2020-12-30 08:57:55 -05:00
Andrew 62063a7250 Updated Dockerfile
created multistage build and tested in compose
2020-12-30 15:56:58 +02:00
Dave Horton 3d58fdd242 dep change to @jambonz/http-authenticator 2020-12-15 14:26:09 -05:00
Dave Horton 12ba6b3968 Merge pull request #7 from jambonz/gh-actions
migrate ci to github actions
2020-12-14 14:50:04 -05:00
Dave Horton ae8469cfee jslint 2020-12-14 14:47:05 -05:00
Dave Horton bf7c09fc83 migrate ci to github actions 2020-12-14 14:44:41 -05:00
Dave Horton 4476c233ff update deps 2020-12-13 14:23:17 -05:00
Dave Horton 45883238e1 update to stats-collector that reconnects when socket dropped 2020-12-11 14:44:57 -05:00
Dave Horton 471f3dc0bb deps 2020-10-26 12:03:56 -04:00
Dave Horton 5ba9058216 update realtimedb-helpers 2020-10-26 10:04:30 -04:00
Dave Horton 6f82454be2 bump deps 2020-10-26 09:29:03 -04:00
Dave Horton 5f60580040 update stats 2020-10-26 09:26:43 -04:00
Dave Horton d0b0feafdc bump deps again 2020-08-18 14:53:41 -04:00
Dave Horton b3e38ab761 update deps 2020-08-18 14:50:56 -04:00
Dave Horton ee16cdd859 deps 2020-07-16 15:59:20 -04:00
Dave Horton 28cfe27b58 update deps 2020-07-09 12:57:50 -04:00
Dave Horton e1ea9dbdf2 update to latest rtpengine-utils 2020-07-09 12:39:08 -04:00
Dave Horton 3fdbeb64f8 update deps and use new rtpengine statistics command 2020-07-09 10:05:40 -04:00
Dave Horton 2204140291 update deps 2020-07-07 13:48:05 -04:00
Dave Horton f01d2140db dont pass Session-Expires header into feature server 2020-06-10 12:04:13 -04:00
Dave Horton ae9b4acf19 update to drachtio-srf@4.4.34 2020-06-08 14:26:59 -04:00
Dave Horton 09a1386283 bugfix: rtpengine now generates internal IP on sdp for internal-facing streams 2020-06-07 14:51:37 -04:00
20 changed files with 5771 additions and 1463 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"jsx": false,
"modules": false
},
"ecmaVersion": 2017
"ecmaVersion": 2018
},
"plugins": ["promise"],
"rules": {
+19
View File
@@ -0,0 +1,19 @@
name: CI
on:
push:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: npm install
- run: npm run jslint
- run: npm test
-9
View File
@@ -1,9 +0,0 @@
sudo: required
language: node_js
node_js:
- "lts/*"
services:
- docker
- mysql
script:
- npm test
+10 -7
View File
@@ -1,13 +1,16 @@
FROM node:lts-alpine
FROM node:alpine as builder
RUN apk update && apk add --no-cache python make g++
WORKDIR /opt/app/
COPY package.json ./
RUN npm install
RUN npm prune
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
FROM node:alpine as app
WORKDIR /opt/app
COPY . /opt/app
COPY --from=builder /opt/app/node_modules ./node_modules
ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app
CMD [ "npm", "start" ]
+1 -1
View File
@@ -1,4 +1,4 @@
# sbc-inbound [![Build Status](https://secure.travis-ci.org/jambonz/sbc-inbound.png)](http://travis-ci.org/jambonz/sbc-inbound)
# sbc-inbound ![Build Status](https://github.com/jambonz/sbc-inbound/workflows/CI/badge.svg)
This application provides a part of the SBC (Session Border Controller) functionality of jambonz. It handles incoming INVITE requests from carrier sip trunks or from sip devices and webrtc applications. SIP INVITEs from known carriers are allowed in, while INVITEs from sip devices are challenged to authenticate. SIP traffic that is allowed in is sent on to a jambonz application server in a private subnet.
+2 -2
View File
@@ -13,10 +13,10 @@ const opts = Object.assign({
timestamp: () => {return `, "time": "${new Date().toISOString()}"`;}
}, {level: process.env.JAMBONES_LOGLEVEL || 'info'});
const logger = require('pino')(opts);
const StatsCollector = require('jambonz-stats-collector');
const StatsCollector = require('@jambonz/stats-collector');
const stats = srf.locals.stats = new StatsCollector(logger);
srf.locals.getFeatureServer = require('./lib/fs-tracking')(srf, logger);
const {getRtpEngine} = require('jambonz-rtpengine-utils')(process.env.JAMBONES_RTPENGINES.split(','), logger, {
const {getRtpEngine} = require('@jambonz/rtpengine-utils')(process.env.JAMBONES_RTPENGINES.split(','), logger, {
emitter: srf.locals.stats
});
srf.locals.getRtpEngine = getRtpEngine;
+42 -26
View File
@@ -79,10 +79,17 @@ class CallSession extends Emitter {
this.logger.info(`uri will be: ${uri}, proxy ${proxy}`);
try {
const response = await this.offer(this.rtpEngineOpts.offer);
debug(`response from rtpengine to offer ${JSON.stringify(response)}`);
const opts = {
...this.rtpEngineOpts.common,
...this.rtpEngineOpts.uac.mediaOpts,
'from-tag': this.rtpEngineOpts.uas.tag,
direction: ['public', 'private'],
sdp: this.req.body
};
const response = await this.offer(opts);
this.logger.debug({opts, response}, 'response from rtpengine to offer');
if ('ok' !== response.result) {
this.logger.error(`rtpengine offer failed with ${JSON.stringify(response)}`);
this.logger.error({}, `rtpengine offer failed with ${JSON.stringify(response)}`);
throw new Error('rtpengine failed: answer');
}
@@ -124,12 +131,18 @@ class CallSession extends Emitter {
proxy,
headers,
responseHeaders,
proxyRequestHeaders: ['all', '-Authorization', '-Max-Forwards', '-Record-Route'],
proxyRequestHeaders: ['all', '-Authorization', '-Max-Forwards', '-Record-Route', '-Session-Expires', 'Min-SE'],
proxyResponseHeaders: ['all'],
localSdpB: response.sdp,
localSdpA: async(sdp, res) => {
this.toTag = res.getParsedHeader('To').params.tag;
const opts = Object.assign({sdp, 'to-tag': this.toTag}, this.rtpEngineOpts.answer);
this.rtpEngineOpts.uac.tag = res.getParsedHeader('To').params.tag;
const opts = {
...this.rtpEngineOpts.common,
...this.rtpEngineOpts.uas.mediaOpts,
'from-tag': this.rtpEngineOpts.uas.tag,
'to-tag': this.rtpEngineOpts.uac.tag,
sdp
};
const response = await this.answer(opts);
if ('ok' !== response.result) {
this.logger.error(`rtpengine answer failed with ${JSON.stringify(response)}`);
@@ -141,7 +154,6 @@ class CallSession extends Emitter {
// successfully connected
this.logger.info('call connected successfully to feature server');
this.toTag = uas.sip.localTag;
this._setHandlers({uas, uac});
return;
} catch (err) {
@@ -190,8 +202,8 @@ class CallSession extends Emitter {
});
});
uas.on('modify', this._onReinvite.bind(this, uas));
uac.on('modify', this._onReinvite.bind(this, uac));
uac.on('modify', this._onFeatureServerReinvite.bind(this, uac));
uac.on('refer', this._onFeatureServerTransfer.bind(this, uac));
uas.on('refer', this._onRefer.bind(this, uas));
@@ -215,6 +227,7 @@ class CallSession extends Emitter {
this.logger.info({opts, response}, 'sent offer for reinvite to rtpengine');
const sdp = await this.uac.modify(response.sdp);
opts = Object.assign(this.rtpEngineOpts.answer, {sdp, 'to-tag': this.toTag});
Object.assign(this.rtpEngineOpts.offer, {'to-tag': this.toTag});
response = await this.answer(opts);
if ('ok' !== response.result) {
res.send(488);
@@ -252,41 +265,44 @@ class CallSession extends Emitter {
async _onReinvite(dlg, req, res) {
try {
let opts = Object.assign(this.rtpEngineOpts.offer, {sdp: req.body});
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;
const answerMedia = dlg.type === 'uas' ? this.rtpEngineOpts.uas.mediaOpts : this.rtpEngineOpts.uac.mediaOpts;
const direction = dlg.type === 'uas' ? ['private', 'public'] : ['public', 'private'];
let opts = {
...this.rtpEngineOpts.common,
...offerMedia,
'from-tag': fromTag,
'to-tag': toTag,
direction,
sdp: req.body,
};
let response = await this.offer(opts);
if ('ok' !== response.result) {
res.send(488);
throw new Error(`_onReinvite: rtpengine failed: offer: ${JSON.stringify(response)}`);
}
this.logger.info({opts, response}, 'sent offer for reinvite to rtpengine');
const sdp = await dlg.other.modify(response.sdp);
opts = Object.assign({sdp, 'to-tag': this.toTag}, this.rtpEngineOpts.answer);
opts = {
...this.rtpEngineOpts.common,
...answerMedia,
'from-tag': fromTag,
'to-tag': toTag,
sdp
};
response = await this.answer(opts);
if ('ok' !== response.result) {
res.send(488);
throw new Error(`_onReinvite: rtpengine failed: ${JSON.stringify(response)}`);
}
this.logger.info({opts, response}, 'sent answer for reinvite to rtpengine');
res.send(200, {body: response.sdp});
} catch (err) {
this.logger.error(err, 'Error handling reinvite');
}
}
async _onFeatureServerReinvite(dlg, req, res) {
try {
const opts = Object.assign({sdp: req.body, 'to-tag': this.toTag}, this.rtpEngineOpts.answer);
const response = await this.answer(opts);
if ('ok' !== response.result) {
res.send(488);
throw new Error(`_onFeatureServerReinvite: rtpengine failed: ${JSON.stringify(response)}`);
}
res.send(200, {body: dlg.local.sdp});
} catch (err) {
this.logger.error(err, 'Error handling reinvite from feature server');
}
}
async _onFeatureServerTransfer(dlg, req, res) {
try {
const referTo = req.getParsedHeader('Refer-To');
+1 -1
View File
@@ -9,7 +9,7 @@ module.exports = (srf, logger) => {
const stats = srf.locals.stats;
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-fs`;
const {createSet} = require('jambonz-realtimedb-helpers')({
const {createSet} = require('@jambonz/realtimedb-helpers')({
host: process.env.JAMBONES_REDIS_HOST || 'localhost',
port: process.env.JAMBONES_REDIS_PORT || 6379
}, logger);
+4 -2
View File
@@ -1,7 +1,9 @@
const debug = require('debug')('jambonz:sbc-inbound');
const Emitter = require('events');
const parseUri = require('drachtio-srf').parseUri;
const msProxyIps = process.env.MS_TEAMS_SIP_PROXY_IPS ? process.env.MS_TEAMS_SIP_PROXY_IPS.split(',').map((i) => i.trim()) : [];
const msProxyIps = process.env.MS_TEAMS_SIP_PROXY_IPS ?
process.env.MS_TEAMS_SIP_PROXY_IPS.split(',').map((i) => i.trim()) :
[];
class AuthOutcomeReporter extends Emitter {
constructor(stats) {
@@ -15,7 +17,7 @@ class AuthOutcomeReporter extends Emitter {
module.exports = function(srf, logger) {
const {lookupSipGatewayBySignalingAddress, lookupAuthHook} = srf.locals.dbHelpers;
const {stats} = srf.locals;
const authenticator = require('jambonz-http-authenticator')(lookupAuthHook, logger, {
const authenticator = require('@jambonz/http-authenticator')(lookupAuthHook, logger, {
blacklistUnknownRealms: true,
emitter: new AuthOutcomeReporter(stats)
});
+15 -10
View File
@@ -12,19 +12,24 @@ function getAppserver(srf) {
}
function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp, teams = false) {
const srtpOpts = teams ? srtpCharacteristics['teams'] : srtpCharacteristics['default'];
const from = req.getParsedHeader('from');
const common = {'call-id': req.get('Call-ID'), 'from-tag': from.params.tag};
const srtpOpts = teams ? srtpCharacteristics['teams'] : srtpCharacteristics['default'];
const dstOpts = dstIsUsingSrtp ? srtpOpts : rtpCharacteristics;
const srctOpts = srcIsUsingSrtp ? srtpOpts : rtpCharacteristics;
const common = {
'call-id': req.get('Call-ID'),
'replace': ['origin', 'session-connection']
};
return {
common,
offer: Object.assign(
{'sdp': req.body, 'replace': ['origin', 'session-connection']},
common,
dstIsUsingSrtp ? srtpOpts : rtpCharacteristics),
answer: Object.assign(
{'replace': ['origin', 'session-connection']},
common,
srcIsUsingSrtp ? srtpOpts : rtpCharacteristics)
uas: {
tag: from.params.tag,
mediaOpts: srctOpts
},
uac: {
tag: null,
mediaOpts: dstOpts
}
};
}
+5594 -1336
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,6 +1,6 @@
{
"name": "sbc-inbound",
"version": "0.3.2",
"version": "0.3.6",
"main": "app.js",
"engines": {
"node": ">= 10.16.0"
@@ -20,28 +20,28 @@
},
"scripts": {
"start": "node app",
"test": "NODE_ENV=test JAMBONES_MYSQL_HOST=localhost JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=error DRACHTIO_SECRET=cymru DRACHTIO_HOST=127.0.0.1 DRACHTIO_PORT=9060 JAMBONES_RTPENGINES=127.0.0.1:12222 JAMBONES_FEATURE_SERVERS=172.38.0.11 node test/ | ./node_modules/.bin/tap-spec",
"test": "NODE_ENV=test JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=error DRACHTIO_SECRET=cymru DRACHTIO_HOST=127.0.0.1 DRACHTIO_PORT=9060 JAMBONES_RTPENGINES=127.0.0.1:12222 JAMBONES_FEATURE_SERVERS=172.38.0.11 node test/ | ./node_modules/.bin/tap-spec",
"coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test",
"jslint": "eslint app.js lib"
},
"dependencies": {
"debug": "^4.1.1",
"@jambonz/db-helpers": "^0.5.12",
"@jambonz/http-authenticator": "^0.1.6",
"@jambonz/realtimedb-helpers": "^0.2.20",
"@jambonz/rtpengine-utils": "^0.1.7",
"@jambonz/stats-collector": "^0.1.4",
"debug": "^4.3.1",
"drachtio-fn-b2b-sugar": "0.0.12",
"drachtio-srf": "^4.4.33",
"@jambonz/db-helpers": "^0.3.6",
"jambonz-http-authenticator": "0.1.5",
"jambonz-realtimedb-helpers": "^0.2.4",
"jambonz-rtpengine-utils": "0.1.1",
"jambonz-stats-collector": "0.0.3",
"pino": "^5.14.0",
"rtpengine-client": "^0.0.8"
"drachtio-srf": "^4.4.44",
"pino": "^6.8.0",
"rtpengine-client": "^0.1.1"
},
"devDependencies": {
"blue-tape": "^1.0.0",
"clear-module": "^4.1.1",
"eslint": "^6.8.0",
"eslint": "^7.15.0",
"eslint-plugin-promise": "^4.2.1",
"nyc": "^15.0.1",
"nyc": "^15.1.0",
"tap-spec": "^5.0.0"
}
}
+3 -4
View File
@@ -1,9 +1,8 @@
const test = require('tape').test ;
const exec = require('child_process').exec ;
const pwd = process.env.TRAVIS ? '' : '-p$MYSQL_ROOT_PASSWORD';
test('creating jambones_test database', (t) => {
exec(`mysql -h localhost -u root ${pwd} < ${__dirname}/db/create_test_db.sql`, (err, stdout, stderr) => {
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp < ${__dirname}/db/create_test_db.sql`, (err, stdout, stderr) => {
if (err) return t.end(err);
t.pass('database successfully created');
t.end();
@@ -11,7 +10,7 @@ test('creating jambones_test database', (t) => {
});
test('creating schema', (t) => {
exec(`mysql -h localhost -u root ${pwd} -D jambones_test < ${__dirname}/db/jambones-sql.sql`, (err, stdout, stderr) => {
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp -D jambones_test < ${__dirname}/db/jambones-sql.sql`, (err, stdout, stderr) => {
if (err) return t.end(err);
t.pass('schema successfully created');
t.end();
@@ -19,7 +18,7 @@ test('creating schema', (t) => {
});
test('populating test case data', (t) => {
exec(`mysql -h localhost -u root ${pwd} -D jambones_test < ${__dirname}/db/populate-test-data.sql`, (err, stdout, stderr) => {
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp -D jambones_test < ${__dirname}/db/populate-test-data.sql`, (err, stdout, stderr) => {
if (err) return t.end(err);
t.pass('test data set created');
t.end();
+2 -2
View File
@@ -1,3 +1,3 @@
create database jambones_test;
create user jambones_test@localhost IDENTIFIED WITH mysql_native_password by 'jambones_test';
grant all on jambones_test.* to jambones_test@localhost;
create user jambones_test@'%' IDENTIFIED WITH mysql_native_password by 'jambones_test';
grant all on jambones_test.* to jambones_test@'%';
+39 -29
View File
@@ -1,6 +1,6 @@
/* SQLEditor (MySQL (2))*/
SET FOREIGN_KEY_CHECKS = 0;
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS call_routes;
@@ -8,10 +8,10 @@ DROP TABLE IF EXISTS lcr_carrier_set_entry;
DROP TABLE IF EXISTS lcr_routes;
DROP TABLE IF EXISTS ms_teams_tenants;
DROP TABLE IF EXISTS api_keys;
DROP TABLE IF EXISTS ms_teams_tenants;
DROP TABLE IF EXISTS sbc_addresses;
DROP TABLE IF EXISTS users;
@@ -22,16 +22,14 @@ DROP TABLE IF EXISTS sip_gateways;
DROP TABLE IF EXISTS voip_carriers;
DROP TABLE IF EXISTS applications;
DROP TABLE IF EXISTS accounts;
DROP TABLE IF EXISTS applications;
DROP TABLE IF EXISTS service_providers;
DROP TABLE IF EXISTS webhooks;
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE call_routes
(
call_route_sid CHAR(36) NOT NULL UNIQUE ,
@@ -51,26 +49,28 @@ priority INTEGER NOT NULL UNIQUE COMMENT 'lower priority routes are attempted f
PRIMARY KEY (lcr_route_sid)
) COMMENT='Least cost routing table';
CREATE TABLE ms_teams_tenants
(
ms_teams_tenant_sid CHAR(36) NOT NULL UNIQUE ,
service_provider_sid CHAR(36) NOT NULL,
account_sid CHAR(36),
application_sid CHAR(36),
tenant_fqdn VARCHAR(255) NOT NULL UNIQUE ,
PRIMARY KEY (ms_teams_tenant_sid)
) COMMENT='A Microsoft Teams customer tenant';
CREATE TABLE api_keys
(
api_key_sid CHAR(36) NOT NULL UNIQUE ,
token CHAR(36) NOT NULL UNIQUE ,
account_sid CHAR(36),
service_provider_sid CHAR(36),
expires_at TIMESTAMP,
expires_at TIMESTAMP NULL DEFAULT NULL,
last_used TIMESTAMP NULL DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (api_key_sid)
) ENGINE=InnoDB COMMENT='An authorization token that is used to access the REST api';
CREATE TABLE ms_teams_tenants
(
ms_teams_tenant_sid CHAR(36) NOT NULL UNIQUE ,
service_provider_sid CHAR(36) NOT NULL,
account_sid CHAR(36) NOT NULL,
application_sid CHAR(36),
tenant_fqdn VARCHAR(255) NOT NULL UNIQUE ,
PRIMARY KEY (ms_teams_tenant_sid)
) COMMENT='A Microsoft Teams customer tenant';
CREATE TABLE sbc_addresses
(
sbc_address_sid CHAR(36) NOT NULL UNIQUE ,
@@ -97,6 +97,11 @@ name VARCHAR(64) NOT NULL UNIQUE ,
description VARCHAR(255),
account_sid CHAR(36) COMMENT 'if provided, indicates this entity represents a customer PBX that is associated with a specific account',
application_sid CHAR(36) COMMENT 'If provided, all incoming calls from this source will be routed to the associated application',
e164_leading_plus BOOLEAN NOT NULL DEFAULT false,
requires_register BOOLEAN NOT NULL DEFAULT false,
register_username VARCHAR(64),
register_sip_realm VARCHAR(64),
register_password VARCHAR(64),
PRIMARY KEY (voip_carrier_sid)
) ENGINE=InnoDB COMMENT='A Carrier or customer PBX that can send or receive calls';
@@ -147,8 +152,9 @@ CREATE TABLE applications
application_sid CHAR(36) NOT NULL UNIQUE ,
name VARCHAR(64) NOT NULL,
account_sid CHAR(36) NOT NULL COMMENT 'account that this application belongs to',
call_hook_sid CHAR(36) COMMENT 'webhook to call for inbound calls to phone numbers owned by this account',
call_hook_sid CHAR(36) COMMENT 'webhook to call for inbound calls ',
call_status_hook_sid CHAR(36) COMMENT 'webhook to call for call status events',
messaging_hook_sid CHAR(36) COMMENT 'webhook to call for inbound SMS/MMS ',
speech_synthesis_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
speech_synthesis_language VARCHAR(12) NOT NULL DEFAULT 'en-US',
speech_synthesis_voice VARCHAR(64),
@@ -185,21 +191,21 @@ ALTER TABLE call_routes ADD FOREIGN KEY account_sid_idxfk (account_sid) REFERENC
ALTER TABLE call_routes ADD FOREIGN KEY application_sid_idxfk (application_sid) REFERENCES applications (application_sid);
CREATE INDEX ms_teams_tenant_sid_idx ON ms_teams_tenants (ms_teams_tenant_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY service_provider_sid_idxfk (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX api_key_sid_idx ON api_keys (api_key_sid);
CREATE INDEX account_sid_idx ON api_keys (account_sid);
ALTER TABLE api_keys ADD FOREIGN KEY account_sid_idxfk_1 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY account_sid_idxfk_1 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX service_provider_sid_idx ON api_keys (service_provider_sid);
ALTER TABLE api_keys ADD FOREIGN KEY service_provider_sid_idxfk (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX ms_teams_tenant_sid_idx ON ms_teams_tenants (ms_teams_tenant_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY service_provider_sid_idxfk_1 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY account_sid_idxfk_2 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY application_sid_idxfk_1 (application_sid) REFERENCES applications (application_sid);
CREATE INDEX tenant_fqdn_idx ON ms_teams_tenants (tenant_fqdn);
CREATE INDEX api_key_sid_idx ON api_keys (api_key_sid);
CREATE INDEX account_sid_idx ON api_keys (account_sid);
ALTER TABLE api_keys ADD FOREIGN KEY account_sid_idxfk_2 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX service_provider_sid_idx ON api_keys (service_provider_sid);
ALTER TABLE api_keys ADD FOREIGN KEY service_provider_sid_idxfk_1 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX sbc_addresses_idx_host_port ON sbc_addresses (ipv4,port);
CREATE INDEX sbc_address_sid_idx ON sbc_addresses (sbc_address_sid);
@@ -241,6 +247,8 @@ ALTER TABLE applications ADD FOREIGN KEY call_hook_sid_idxfk (call_hook_sid) REF
ALTER TABLE applications ADD FOREIGN KEY call_status_hook_sid_idxfk (call_status_hook_sid) REFERENCES webhooks (webhook_sid);
ALTER TABLE applications ADD FOREIGN KEY messaging_hook_sid_idxfk (messaging_hook_sid) REFERENCES webhooks (webhook_sid);
CREATE INDEX service_provider_sid_idx ON service_providers (service_provider_sid);
CREATE INDEX name_idx ON service_providers (name);
CREATE INDEX root_domain_idx ON service_providers (root_domain);
@@ -254,3 +262,5 @@ ALTER TABLE accounts ADD FOREIGN KEY service_provider_sid_idxfk_3 (service_provi
ALTER TABLE accounts ADD FOREIGN KEY registration_hook_sid_idxfk_1 (registration_hook_sid) REFERENCES webhooks (webhook_sid);
ALTER TABLE accounts ADD FOREIGN KEY device_calling_application_sid_idxfk (device_calling_application_sid) REFERENCES applications (application_sid);
SET FOREIGN_KEY_CHECKS=1;
+1 -1
View File
@@ -7,7 +7,7 @@ values ('ed649e33-e771-403a-8c99-1780eabbc803', '3f35518f-5a0d-4c2e-90a5-2407bb3
insert into voip_carriers (voip_carrier_sid, name) values ('287c1452-620d-4195-9f19-c9814ef90d78', 'westco');
insert into sip_gateways (sip_gateway_sid, voip_carrier_sid, ipv4, inbound, outbound)
values ('124a5339-c62c-4075-9e19-f4de70a96597', '287c1452-620d-4195-9f19-c9814ef90d78', '172.38.0.20', true, true);
values ('124a5339-c62c-4075-9e19-f4de70a96597', '287c1452-620d-4195-9f19-c9814ef90d78', '172.38.0.20/32', true, true);
insert into sip_gateways (sip_gateway_sid, voip_carrier_sid, ipv4, port, inbound, outbound)
values ('efbc4830-57cd-4c78-a56f-d64fdf210fe8', '287c1452-620d-4195-9f19-c9814ef90d78', '3.3.3.3', 5062, false, true);
+18 -1
View File
@@ -7,7 +7,20 @@ networks:
config:
- subnet: 172.38.0.0/16
services:
services:
mysql:
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "--protocol", "tcp"]
timeout: 5s
retries: 10
networks:
sbc-inbound:
ipv4_address: 172.38.0.2
sbc:
image: drachtio/drachtio-server:latest
command: drachtio --contact "sip:*;transport=udp" --loglevel debug --sofia-loglevel 9
@@ -16,6 +29,9 @@ services:
networks:
sbc-inbound:
ipv4_address: 172.38.0.10
depends_on:
mysql:
condition: service_healthy
appserver:
image: drachtio/sipp:latest
@@ -47,6 +63,7 @@ services:
rtpengine:
image: drachtio/rtpengine:latest
command: rtpengine --interface private/172.38.0.14 --interface public/172.38.0.14!172.38.0.14
ports:
- "12222:22222/udp"
networks:
-1
View File
@@ -1,5 +1,4 @@
require('./docker_start');
require('./create-test-db');
require('./sip-tests');
require('./remove-test-db');
require('./docker_stop');
-11
View File
@@ -1,11 +0,0 @@
const test = require('tape').test ;
const exec = require('child_process').exec ;
const pwd = process.env.TRAVIS ? '' : '-p$MYSQL_ROOT_PASSWORD';
test('dropping jambones_test database', (t) => {
exec(`mysql -h localhost -u root ${pwd} < ${__dirname}/db/remove_test_db.sql`, (err, stdout, stderr) => {
if (err) return t.end(err);
t.pass('database successfully dropped');
t.end();
});
});
+6 -6
View File
@@ -1,5 +1,5 @@
const { spawn } = require('child_process');
const debug = require('debug')('test:sipp');
const debug = require('debug')('jambonz:ci');
let network;
const obj = {};
let output = '';
@@ -27,7 +27,7 @@ obj.output = () => {
obj.sippUac = (file, bindAddress) => {
const cmd = 'docker';
const args = [
'run', '-ti', '--rm', '--net', `${network}`,
'run', '--rm', '--net', `${network}`,
'-v', `${__dirname}/scenarios:/tmp/scenarios`,
'drachtio/sipp', 'sipp', '-sf', `/tmp/scenarios/${file}`,
'-m', '1',
@@ -37,7 +37,7 @@ obj.sippUac = (file, bindAddress) => {
'sbc'
];
if (bindAddress) args.splice(5, 0, '--ip', bindAddress);
if (bindAddress) args.splice(4, 0, '--ip', bindAddress);
//console.log(args.join(' '));
clearOutput();
@@ -57,11 +57,11 @@ obj.sippUac = (file, bindAddress) => {
});
child_process.stdout.on('data', (data) => {
//debug(`stdout: ${data}`);
debug(`stderr: ${data}`);
addOutput(data.toString());
});
child_process.stdout.on('data', (data) => {
//debug(`stdout: ${data}`);
child_process.stderr.on('data', (data) => {
debug(`stderr: ${data}`);
addOutput(data.toString());
});
});