mirror of
https://github.com/jambonz/sbc-outbound.git
synced 2026-01-25 02:07:59 +00:00
add support for ms teams and bugfix for reinvite handling from network side
This commit is contained in:
7
app.js
7
app.js
@@ -18,14 +18,14 @@ const StatsCollector = require('jambonz-stats-collector');
|
|||||||
const stats = srf.locals.stats = new StatsCollector(logger);
|
const stats = srf.locals.stats = new StatsCollector(logger);
|
||||||
const {route, setLogger} = require('./lib/middleware');
|
const {route, setLogger} = require('./lib/middleware');
|
||||||
const CallSession = require('./lib/call-session');
|
const CallSession = require('./lib/call-session');
|
||||||
const {performLcr} = require('jambonz-db-helpers')({
|
const {performLcr, lookupAllTeamsFQDNs} = require('@jambonz/db-helpers')({
|
||||||
host: process.env.JAMBONES_MYSQL_HOST,
|
host: process.env.JAMBONES_MYSQL_HOST,
|
||||||
user: process.env.JAMBONES_MYSQL_USER,
|
user: process.env.JAMBONES_MYSQL_USER,
|
||||||
password: process.env.JAMBONES_MYSQL_PASSWORD,
|
password: process.env.JAMBONES_MYSQL_PASSWORD,
|
||||||
database: process.env.JAMBONES_MYSQL_DATABASE,
|
database: process.env.JAMBONES_MYSQL_DATABASE,
|
||||||
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
||||||
}, logger);
|
}, logger);
|
||||||
srf.locals.dbHelpers = {performLcr};
|
srf.locals.dbHelpers = {performLcr, lookupAllTeamsFQDNs};
|
||||||
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
|
emitter: srf.locals.stats
|
||||||
});
|
});
|
||||||
@@ -61,4 +61,7 @@ setInterval(() => {
|
|||||||
stats.gauge('sbc.sip.calls.count', activeCallIds.size, ['direction:outbound']);
|
stats.gauge('sbc.sip.calls.count', activeCallIds.size, ['direction:outbound']);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
|
const {pingMsTeamsGateways} = require('./lib/utils');
|
||||||
|
pingMsTeamsGateways(logger, srf);
|
||||||
|
|
||||||
module.exports = {srf};
|
module.exports = {srf};
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
{
|
{
|
||||||
"transport-protocol": "UDP/TLS/RTP/SAVPF",
|
"default": {
|
||||||
"ICE": "force",
|
"transport-protocol": "UDP/TLS/RTP/SAVPF",
|
||||||
"SDES": "off",
|
"ICE": "force",
|
||||||
"flags": ["generate mid", "SDES-no"],
|
"SDES": "off",
|
||||||
"rtcp-mux": ["require"]
|
"flags": ["generate mid", "SDES-no", "media handover"],
|
||||||
|
"rtcp-mux": ["require"]
|
||||||
|
},
|
||||||
|
"teams": {
|
||||||
|
"transport-protocol": "RTP/SAVP",
|
||||||
|
"ICE": "force",
|
||||||
|
"flags": ["generate mid", "media handover",
|
||||||
|
"SDES-no-AES_CM_128_HMAC_SHA1_32",
|
||||||
|
"SDES-no-F8_128_HMAC_SHA1_80",
|
||||||
|
"SDES-no-F8_128_HMAC_SHA1_32",
|
||||||
|
"SDES-no-NULL_HMAC_SHA1_80",
|
||||||
|
"SDES-no-NULL_HMAC_SHA1_32",
|
||||||
|
"SDES-no-AES_192_CM_HMAC_SHA1_80",
|
||||||
|
"SDES-no-AES_192_CM_HMAC_SHA1_32",
|
||||||
|
"SDES-no-AES_256_CM_HMAC_SHA1_80",
|
||||||
|
"SDES-no-AES_256_CM_HMAC_SHA1_32"
|
||||||
|
],
|
||||||
|
"rtcp-mux": ["require"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,17 +9,20 @@ const debug = require('debug')('jambonz:sbc-outbound');
|
|||||||
* this is to make sure the outgoing From has the number in the incoming From
|
* this is to make sure the outgoing From has the number in the incoming From
|
||||||
* and not the incoming PAI
|
* and not the incoming PAI
|
||||||
*/
|
*/
|
||||||
const createBLegFromHeader = (req) => {
|
const createBLegFromHeader = (req, teams) => {
|
||||||
const from = req.getParsedHeader('From');
|
const from = req.getParsedHeader('From');
|
||||||
|
const host = teams ? req.get('X-MS-Teams-Tenant-FQDN') : 'localhost';
|
||||||
const uri = parseUri(from.uri);
|
const uri = parseUri(from.uri);
|
||||||
if (uri && uri.user) return `sip:${uri.user}@localhost`;
|
//if (uri && uri.user) return `sip:${uri.user}@${host}`;
|
||||||
return 'sip:anonymous@localhost';
|
if (uri && uri.user) return `sip:+15085710838@${host}`;
|
||||||
|
return `sip:anonymous@${host}`;
|
||||||
};
|
};
|
||||||
const createBLegToHeader = (req) => {
|
const createBLegToHeader = (req, teams) => {
|
||||||
const from = req.getParsedHeader('To');
|
const to = req.getParsedHeader('To');
|
||||||
const uri = parseUri(from.uri);
|
const host = teams ? req.get('X-MS-Teams-Tenant-FQDN') : 'localhost';
|
||||||
if (uri && uri.user) return `sip:${uri.user}@localhost`;
|
const uri = parseUri(to.uri);
|
||||||
return 'sip:localhost';
|
if (uri && uri.user) return `sip:${uri.user}@${host}`;
|
||||||
|
return `sip:anonymous@${host}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CallSession extends Emitter {
|
class CallSession extends Emitter {
|
||||||
@@ -36,6 +39,7 @@ class CallSession extends Emitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async connect() {
|
async connect() {
|
||||||
|
const teams = this.teams = this.req.locals.target === 'teams';
|
||||||
const engine = this.srf.locals.getRtpEngine();
|
const engine = this.srf.locals.getRtpEngine();
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
this.logger.info('No available rtpengines, rejecting call!');
|
this.logger.info('No available rtpengines, rejecting call!');
|
||||||
@@ -49,13 +53,19 @@ class CallSession extends Emitter {
|
|||||||
this.answer = answer;
|
this.answer = answer;
|
||||||
this.del = del;
|
this.del = del;
|
||||||
|
|
||||||
this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, this.useWss);
|
this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, this.useWss || teams, teams);
|
||||||
this.rtpEngineResource = {destroy: this.del.bind(null, this.rtpEngineOpts.common)};
|
this.rtpEngineResource = {destroy: this.del.bind(null, this.rtpEngineOpts.common)};
|
||||||
let proxy, uris;
|
let proxy, uris;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// determine where to send the call
|
// determine where to send the call
|
||||||
debug(`connecting call: ${JSON.stringify(this.req.locals)}`);
|
debug(`connecting call: ${JSON.stringify(this.req.locals)}`);
|
||||||
|
const headers = {
|
||||||
|
'From': createBLegFromHeader(this.req, teams),
|
||||||
|
'To': createBLegToHeader(this.req, teams),
|
||||||
|
Allow: 'INVITE, ACK, OPTIONS, CANCEL, BYE, NOTIFY, UPDATE, PRACK'
|
||||||
|
};
|
||||||
|
|
||||||
if (this.req.locals.registration) {
|
if (this.req.locals.registration) {
|
||||||
debug(`sending call to user ${JSON.stringify(this.req.locals.registration)}`);
|
debug(`sending call to user ${JSON.stringify(this.req.locals.registration)}`);
|
||||||
const contact = this.req.locals.registration.contact;
|
const contact = this.req.locals.registration.contact;
|
||||||
@@ -70,6 +80,17 @@ class CallSession extends Emitter {
|
|||||||
else if (this.req.locals.target === 'forward') {
|
else if (this.req.locals.target === 'forward') {
|
||||||
uris = [this.req.uri];
|
uris = [this.req.uri];
|
||||||
}
|
}
|
||||||
|
else if (teams) {
|
||||||
|
const vmailParam = 'opaque=app:voicemail';
|
||||||
|
proxy = `sip:${this.req.calledNumber}@sip.pstnhub.microsoft.com:5061;transport=tls`;
|
||||||
|
if (this.req.uri.includes(vmailParam)) {
|
||||||
|
uris = [`sip:${this.req.calledNumber}@sip.pstnhub.microsoft.com;${vmailParam}`];
|
||||||
|
}
|
||||||
|
else uris = [`sip:${this.req.calledNumber}@sip.pstnhub.microsoft.com`];
|
||||||
|
Object.assign(headers, {
|
||||||
|
Contact: `sip:${this.req.calledNumber}@${this.req.get('X-MS-Teams-Tenant-FQDN')}:5061;transport=tls`
|
||||||
|
});
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
debug('calling lcr');
|
debug('calling lcr');
|
||||||
try {
|
try {
|
||||||
@@ -114,17 +135,13 @@ class CallSession extends Emitter {
|
|||||||
const {uas, uac} = await this.srf.createB2BUA(this.req, this.res, uri, {
|
const {uas, uac} = await this.srf.createB2BUA(this.req, this.res, uri, {
|
||||||
proxy,
|
proxy,
|
||||||
passFailure: false,
|
passFailure: false,
|
||||||
proxyRequestHeaders: ['all'],
|
proxyRequestHeaders: ['all', '-X-MS-Teams-FQDN', '-X-MS-Teams-Tenant-FQDN', '-Allow'],
|
||||||
proxyResponseHeaders: ['all'],
|
proxyResponseHeaders: ['all', '-Allow'],
|
||||||
headers: {
|
headers,
|
||||||
'From': createBLegFromHeader(this.req),
|
|
||||||
'To': createBLegToHeader(this.req)
|
|
||||||
},
|
|
||||||
localSdpB: response.sdp,
|
localSdpB: response.sdp,
|
||||||
localSdpA: async(sdp, res) => {
|
localSdpA: async(sdp, res) => {
|
||||||
this.toTag = res.getParsedHeader('To').params.tag;
|
this.toTag = res.getParsedHeader('To').params.tag;
|
||||||
const opts = Object.assign({sdp, 'to-tag': this.toTag},
|
const opts = Object.assign(this.rtpEngineOpts.answer, {sdp, 'to-tag': this.toTag});
|
||||||
this.rtpEngineOpts.answer);
|
|
||||||
const response = await this.answer(opts);
|
const response = await this.answer(opts);
|
||||||
this.logger.debug({answer: opts, response}, 'rtpengine answer');
|
this.logger.debug({answer: opts, response}, 'rtpengine answer');
|
||||||
if ('ok' !== response.result) {
|
if ('ok' !== response.result) {
|
||||||
@@ -202,19 +219,18 @@ class CallSession extends Emitter {
|
|||||||
|
|
||||||
|
|
||||||
// default forwarding of other request types
|
// default forwarding of other request types
|
||||||
forwardInDialogRequests(uac);
|
forwardInDialogRequests(uac, ['info', 'notify', 'options', 'message']);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onReinvite(dlg, req, res) {
|
async _onReinvite(dlg, req, res) {
|
||||||
try {
|
try {
|
||||||
let response = await this.offer(Object.assign({sdp: req.body}, this.rtpEngineOpts.offer));
|
let response = await this.offer(Object.assign(this.rtpEngineOpts.offer, {sdp: req.body}));
|
||||||
if ('ok' !== response.result) {
|
if ('ok' !== response.result) {
|
||||||
res.send(488);
|
res.send(488);
|
||||||
throw new Error(`_onReinvite: rtpengine failed: offer: ${JSON.stringify(response)}`);
|
throw new Error(`_onReinvite: rtpengine failed: offer: ${JSON.stringify(response)}`);
|
||||||
}
|
}
|
||||||
const sdp = await dlg.other.modify(response.sdp);
|
const sdp = await dlg.other.modify(response.sdp);
|
||||||
const opts = Object.assign({sdp, 'to-tag': res.getParsedHeader('To').params.tag},
|
const opts = Object.assign(this.rtpEngineOpts.answer, {sdp, 'to-tag': res.getParsedHeader('To').params.tag});
|
||||||
this.rtpEngineOpts.answer);
|
|
||||||
response = await this.answer(opts);
|
response = await this.answer(opts);
|
||||||
if ('ok' !== response.result) {
|
if ('ok' !== response.result) {
|
||||||
res.send(488);
|
res.send(488);
|
||||||
@@ -228,16 +244,27 @@ class CallSession extends Emitter {
|
|||||||
|
|
||||||
async _onNetworkReinvite(dlg, req, res) {
|
async _onNetworkReinvite(dlg, req, res) {
|
||||||
try {
|
try {
|
||||||
const opts = Object.assign({sdp: req.body, 'to-tag': this.toTag}, this.rtpEngineOpts.answer);
|
const newAnswerOpts = Object.assign({}, this.rtpEngineOpts.answer, {sdp: req.body});
|
||||||
const response = await this.answer(opts);
|
let response = await this.answer(newAnswerOpts);
|
||||||
this.logger.debug({answer: opts, response}, '_onNetworkReinvite: rtpengine answer');
|
this.logger.debug({answer: newAnswerOpts, response}, '_onNetworkReinvite: answer to rtpengine');
|
||||||
if ('ok' !== response.result) {
|
if ('ok' !== response.result) {
|
||||||
res.send(488);
|
res.send(488);
|
||||||
throw new Error(`_onFeatureServerReinvite: rtpengine failed: ${JSON.stringify(response)}`);
|
throw new Error(`_onReinvite: rtpengine failed: offer: ${JSON.stringify(response)}`);
|
||||||
}
|
}
|
||||||
res.send(200, {body: dlg.local.sdp});
|
|
||||||
|
// reinvite feature server
|
||||||
|
const sdp = await dlg.other.modify(response.sdp);
|
||||||
|
|
||||||
|
const newOfferOpts = Object.assign({}, this.rtpEngineOpts.offer, {sdp, 'to-tag': this.toTag});
|
||||||
|
response = await this.offer(newOfferOpts);
|
||||||
|
this.logger.debug({answer: newOfferOpts, response}, '_onNetworkReinvite: offer to rtpengine');
|
||||||
|
if ('ok' !== response.result) {
|
||||||
|
res.send(488);
|
||||||
|
throw new Error(`_onReinvite: rtpengine failed: ${JSON.stringify(response)}`);
|
||||||
|
}
|
||||||
|
res.send(200, {body: response.sdp});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.error(err, 'Error handling reinvite from feature server');
|
this.logger.error(err, 'Error handling reinvite');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +285,7 @@ class CallSession extends Emitter {
|
|||||||
if (req.has('X-Retain-Call-Sid')) {
|
if (req.has('X-Retain-Call-Sid')) {
|
||||||
Object.assign(headers, {'X-Retain-Call-Sid': req.get('X-Retain-Call-Sid')});
|
Object.assign(headers, {'X-Retain-Call-Sid': req.get('X-Retain-Call-Sid')});
|
||||||
}
|
}
|
||||||
const dlg = await this.srf.createUAC(referTo.uri, {localSdp: dlg.local.sdp, proxyRequestHeaders});
|
const dlg = await this.srf.createUAC(referTo.uri, {localSdp: dlg.local.sdp, headers});
|
||||||
this.uas.destroy();
|
this.uas.destroy();
|
||||||
|
|
||||||
this.uas = dlg;
|
this.uas = dlg;
|
||||||
|
|||||||
@@ -43,7 +43,12 @@ function route(opts) {
|
|||||||
let reg;
|
let reg;
|
||||||
const dotDecimalHost = /^[0-9\.]+$/.test(uri.host);
|
const dotDecimalHost = /^[0-9\.]+$/.test(uri.host);
|
||||||
|
|
||||||
if (!dotDecimalHost) {
|
if (req.has('X-MS-Teams-FQDN') && req.has('X-MS-Teams-Tenant-FQDN')) {
|
||||||
|
logger.debug('This is a call to ms teams');
|
||||||
|
req.locals.target = 'teams';
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
else if (!dotDecimalHost) {
|
||||||
// uri host is not a dot-decimal address, so try to look up user
|
// uri host is not a dot-decimal address, so try to look up user
|
||||||
debug(`searching for registered user ${aor}`);
|
debug(`searching for registered user ${aor}`);
|
||||||
reg = await registrar.query(aor);
|
reg = await registrar.query(aor);
|
||||||
|
|||||||
49
lib/utils.js
49
lib/utils.js
@@ -2,14 +2,20 @@ const rtpCharacteristics = require('../data/rtp-transcoding');
|
|||||||
const srtpCharacteristics = require('../data/srtp-transcoding');
|
const srtpCharacteristics = require('../data/srtp-transcoding');
|
||||||
const debug = require('debug')('jambonz:sbc-outbound');
|
const debug = require('debug')('jambonz:sbc-outbound');
|
||||||
|
|
||||||
function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp) {
|
function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp, teams = false) {
|
||||||
const from = req.getParsedHeader('from');
|
const from = req.getParsedHeader('from');
|
||||||
|
const srtpOpts = teams ? srtpCharacteristics['teams'] : srtpCharacteristics['default'];
|
||||||
const common = {'call-id': req.get('Call-ID'), 'from-tag': from.params.tag};
|
const common = {'call-id': req.get('Call-ID'), 'from-tag': from.params.tag};
|
||||||
return {
|
return {
|
||||||
common,
|
common,
|
||||||
offer: Object.assign({'sdp': req.body, 'replace': ['origin', 'session-connection']}, common,
|
offer: Object.assign(
|
||||||
dstIsUsingSrtp ? srtpCharacteristics : rtpCharacteristics),
|
{'sdp': req.body, 'replace': ['origin', 'session-connection']},
|
||||||
answer: Object.assign({}, common, srcIsUsingSrtp ? srtpCharacteristics : rtpCharacteristics)
|
common,
|
||||||
|
dstIsUsingSrtp ? srtpOpts : rtpCharacteristics),
|
||||||
|
answer: Object.assign(
|
||||||
|
{'replace': ['origin', 'session-connection']},
|
||||||
|
common,
|
||||||
|
srcIsUsingSrtp ? srtpOpts : rtpCharacteristics)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +33,40 @@ function selectHostPort(hostport, protocol) {
|
|||||||
return sel[0];
|
return sel[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pingMs(logger, srf, gateway, fqdns) {
|
||||||
|
const uri = `sip:${gateway}`;
|
||||||
|
const proxy = `sip:${gateway}:5061;transport=tls`;
|
||||||
|
fqdns.forEach((fqdn) => {
|
||||||
|
const contact = `<sip:${fqdn}:5061;transport=tls>`;
|
||||||
|
srf.request(uri, {
|
||||||
|
method: 'OPTIONS',
|
||||||
|
proxy,
|
||||||
|
headers: {
|
||||||
|
'Contact': contact,
|
||||||
|
'From': contact,
|
||||||
|
}
|
||||||
|
}).catch((err) => logger.error(err, `Error pinging MS Teams at ${gateway}`));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function pingMsTeamsGateways(logger, srf) {
|
||||||
|
const {lookupAllTeamsFQDNs} = srf.locals.dbHelpers;
|
||||||
|
lookupAllTeamsFQDNs()
|
||||||
|
.then((fqdns) => {
|
||||||
|
if (fqdns.length > 0) {
|
||||||
|
['sip.pstnhub.microsoft.com', 'sip2.pstnhub.microsoft.com', 'sip3.pstnhub.microsoft.com']
|
||||||
|
.forEach((gw) => {
|
||||||
|
setInterval(pingMs.bind(this, logger, srf, gw, fqdns), 60000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
logger.error(err, 'Error looking up all ms teams fqdns');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
makeRtpEngineOpts,
|
makeRtpEngineOpts,
|
||||||
selectHostPort
|
selectHostPort,
|
||||||
|
pingMsTeamsGateways
|
||||||
};
|
};
|
||||||
|
|||||||
38
package-lock.json
generated
38
package-lock.json
generated
@@ -257,6 +257,23 @@
|
|||||||
"integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
|
"integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@jambonz/db-helpers": {
|
||||||
|
"version": "0.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/db-helpers/-/db-helpers-0.3.8.tgz",
|
||||||
|
"integrity": "sha512-w2eiWThEsjL4xERqkV7Ot4BU7HWxZxyarcoCubY0QekyGruUamnEys3KsvZ26oGKYfYpnJEj5jI9WRYcu5QqmQ==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"mysql2": "^2.0.2",
|
||||||
|
"uuid": "^7.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "7.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
|
||||||
|
"integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/color-name": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
@@ -744,9 +761,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"drachtio-srf": {
|
"drachtio-srf": {
|
||||||
"version": "4.4.28",
|
"version": "4.4.33",
|
||||||
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.28.tgz",
|
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.33.tgz",
|
||||||
"integrity": "sha512-gY/wmH6JFmeEv2/jhwFbky1NYUmDwgIJzjNeGlDiAkQEA6GgcI/CFi5RRHAUzghpczTwXQNDXpARPB8QDWX1JA==",
|
"integrity": "sha512-2bVOObbP9m9ASZ+XXgnaeEk9v1a2Vn8d4Oaz6anrRCuRUzirUOJ/c5nJh9VQvbmXqUx+VubPmXa+AGJuFyYNow==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async": "^1.4.2",
|
"async": "^1.4.2",
|
||||||
"debug": "^3.1.0",
|
"debug": "^3.1.0",
|
||||||
@@ -757,6 +774,7 @@
|
|||||||
"lodash": "^4.17.13",
|
"lodash": "^4.17.13",
|
||||||
"node-noop": "0.0.1",
|
"node-noop": "0.0.1",
|
||||||
"only": "0.0.2",
|
"only": "0.0.2",
|
||||||
|
"sdp-transform": "^2.14.0",
|
||||||
"sip-methods": "^0.3.0",
|
"sip-methods": "^0.3.0",
|
||||||
"utils-merge": "1.0.0",
|
"utils-merge": "1.0.0",
|
||||||
"uuid": "^3.0.0"
|
"uuid": "^3.0.0"
|
||||||
@@ -1665,15 +1683,6 @@
|
|||||||
"istanbul-lib-report": "^3.0.0"
|
"istanbul-lib-report": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jambonz-db-helpers": {
|
|
||||||
"version": "0.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/jambonz-db-helpers/-/jambonz-db-helpers-0.3.2.tgz",
|
|
||||||
"integrity": "sha512-j7AEgts+Bj1CFPiM0estFmWmdDTZKWbkeIPY1QT3BR0cLClzjqo9fmdCzLoDtk/NWMy7IPNEQpVHzEejxFHq9g==",
|
|
||||||
"requires": {
|
|
||||||
"debug": "^4.1.1",
|
|
||||||
"mysql2": "^2.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jambonz-mw-registrar": {
|
"jambonz-mw-registrar": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/jambonz-mw-registrar/-/jambonz-mw-registrar-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/jambonz-mw-registrar/-/jambonz-mw-registrar-0.1.2.tgz",
|
||||||
@@ -2406,6 +2415,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"sdp-transform": {
|
||||||
|
"version": "2.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-2.14.0.tgz",
|
||||||
|
"integrity": "sha512-8ZYOau/o9PzRhY0aMuRzvmiM6/YVQR8yjnBScvZHSdBnywK5oZzAJK+412ZKkDq29naBmR3bRw8MFu0C01Gehg=="
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
|
|||||||
@@ -29,9 +29,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"drachtio-fn-b2b-sugar": "^0.0.12",
|
"drachtio-fn-b2b-sugar": "^0.0.12",
|
||||||
"drachtio-srf": "^4.4.28",
|
"drachtio-srf": "^4.4.33",
|
||||||
"jambonz-rtpengine-utils": "0.1.1",
|
"jambonz-rtpengine-utils": "0.1.1",
|
||||||
"jambonz-db-helpers": "^0.3.2",
|
"@jambonz/db-helpers": "^0.3.8",
|
||||||
"jambonz-mw-registrar": "^0.1.2",
|
"jambonz-mw-registrar": "^0.1.2",
|
||||||
"jambonz-stats-collector": "0.0.3",
|
"jambonz-stats-collector": "0.0.3",
|
||||||
"pino": "^5.14.0",
|
"pino": "^5.14.0",
|
||||||
|
|||||||
@@ -2,203 +2,255 @@
|
|||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `call_routes`;
|
DROP TABLE IF EXISTS call_routes;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `lcr_carrier_set_entry`;
|
DROP TABLE IF EXISTS lcr_carrier_set_entry;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `lcr_routes`;
|
DROP TABLE IF EXISTS lcr_routes;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `api_keys`;
|
DROP TABLE IF EXISTS ms_teams_tenants;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `phone_numbers`;
|
DROP TABLE IF EXISTS api_keys;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `sip_gateways`;
|
DROP TABLE IF EXISTS sbc_addresses;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `voip_carriers`;
|
DROP TABLE IF EXISTS users;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `accounts`;
|
DROP TABLE IF EXISTS phone_numbers;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `applications`;
|
DROP TABLE IF EXISTS sip_gateways;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `service_providers`;
|
DROP TABLE IF EXISTS voip_carriers;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `webhooks`;
|
DROP TABLE IF EXISTS applications;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS accounts;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS service_providers;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS webhooks;
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `call_routes`
|
CREATE TABLE call_routes
|
||||||
(
|
(
|
||||||
`call_route_sid` CHAR(36) NOT NULL UNIQUE ,
|
call_route_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`priority` INTEGER NOT NULL,
|
priority INTEGER NOT NULL,
|
||||||
`account_sid` CHAR(36) NOT NULL,
|
account_sid CHAR(36) NOT NULL,
|
||||||
`regex` VARCHAR(255) NOT NULL,
|
regex VARCHAR(255) NOT NULL,
|
||||||
`application_sid` CHAR(36) NOT NULL,
|
application_sid CHAR(36) NOT NULL,
|
||||||
PRIMARY KEY (`call_route_sid`)
|
PRIMARY KEY (call_route_sid)
|
||||||
) ENGINE=InnoDB COMMENT='a regex-based pattern match for call routing';
|
) ENGINE=InnoDB COMMENT='a regex-based pattern match for call routing';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `lcr_routes`
|
CREATE TABLE lcr_routes
|
||||||
(
|
(
|
||||||
`lcr_route_sid` CHAR(36),
|
lcr_route_sid CHAR(36),
|
||||||
`regex` VARCHAR(32) NOT NULL COMMENT 'regex-based pattern match against dialed number, used for LCR routing of PSTN calls',
|
regex VARCHAR(32) NOT NULL COMMENT 'regex-based pattern match against dialed number, used for LCR routing of PSTN calls',
|
||||||
`description` VARCHAR(1024),
|
description VARCHAR(1024),
|
||||||
`priority` INTEGER NOT NULL UNIQUE COMMENT 'lower priority routes are attempted first',
|
priority INTEGER NOT NULL UNIQUE COMMENT 'lower priority routes are attempted first',
|
||||||
PRIMARY KEY (`lcr_route_sid`)
|
PRIMARY KEY (lcr_route_sid)
|
||||||
) COMMENT='Least cost routing table';
|
) COMMENT='Least cost routing table';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `api_keys`
|
CREATE TABLE ms_teams_tenants
|
||||||
(
|
(
|
||||||
`api_key_sid` CHAR(36) NOT NULL UNIQUE ,
|
ms_teams_tenant_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`token` CHAR(36) NOT NULL UNIQUE ,
|
service_provider_sid CHAR(36) NOT NULL,
|
||||||
`account_sid` CHAR(36),
|
account_sid CHAR(36),
|
||||||
`service_provider_sid` CHAR(36),
|
application_sid CHAR(36),
|
||||||
PRIMARY KEY (`api_key_sid`)
|
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,
|
||||||
|
PRIMARY KEY (api_key_sid)
|
||||||
) ENGINE=InnoDB COMMENT='An authorization token that is used to access the REST api';
|
) ENGINE=InnoDB COMMENT='An authorization token that is used to access the REST api';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `voip_carriers`
|
CREATE TABLE sbc_addresses
|
||||||
(
|
(
|
||||||
`voip_carrier_sid` CHAR(36) NOT NULL UNIQUE ,
|
sbc_address_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`name` VARCHAR(64) NOT NULL UNIQUE ,
|
ipv4 VARCHAR(255) NOT NULL,
|
||||||
`description` VARCHAR(255),
|
port INTEGER NOT NULL DEFAULT 5060,
|
||||||
`account_sid` CHAR(36) COMMENT 'if provided, indicates this entity represents a customer PBX that is associated with a specific account',
|
service_provider_sid CHAR(36),
|
||||||
`application_sid` CHAR(36) COMMENT 'If provided, all incoming calls from this source will be routed to the associated application',
|
PRIMARY KEY (sbc_address_sid)
|
||||||
PRIMARY KEY (`voip_carrier_sid`)
|
);
|
||||||
|
|
||||||
|
CREATE TABLE users
|
||||||
|
(
|
||||||
|
user_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
|
name CHAR(36) NOT NULL UNIQUE ,
|
||||||
|
hashed_password VARCHAR(1024) NOT NULL,
|
||||||
|
salt CHAR(16) NOT NULL,
|
||||||
|
force_change BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
PRIMARY KEY (user_sid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE voip_carriers
|
||||||
|
(
|
||||||
|
voip_carrier_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
|
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',
|
||||||
|
PRIMARY KEY (voip_carrier_sid)
|
||||||
) ENGINE=InnoDB COMMENT='A Carrier or customer PBX that can send or receive calls';
|
) ENGINE=InnoDB COMMENT='A Carrier or customer PBX that can send or receive calls';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `phone_numbers`
|
CREATE TABLE phone_numbers
|
||||||
(
|
(
|
||||||
`phone_number_sid` CHAR(36) UNIQUE ,
|
phone_number_sid CHAR(36) UNIQUE ,
|
||||||
`number` VARCHAR(32) NOT NULL UNIQUE ,
|
number VARCHAR(32) NOT NULL UNIQUE ,
|
||||||
`voip_carrier_sid` CHAR(36) NOT NULL,
|
voip_carrier_sid CHAR(36) NOT NULL,
|
||||||
`account_sid` CHAR(36),
|
account_sid CHAR(36),
|
||||||
`application_sid` CHAR(36),
|
application_sid CHAR(36),
|
||||||
PRIMARY KEY (`phone_number_sid`)
|
PRIMARY KEY (phone_number_sid)
|
||||||
) ENGINE=InnoDB COMMENT='A phone number that has been assigned to an account';
|
) ENGINE=InnoDB COMMENT='A phone number that has been assigned to an account';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `webhooks`
|
CREATE TABLE webhooks
|
||||||
(
|
(
|
||||||
`webhook_sid` CHAR(36) NOT NULL UNIQUE ,
|
webhook_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`url` VARCHAR(1024) NOT NULL,
|
url VARCHAR(1024) NOT NULL,
|
||||||
`method` ENUM("GET","POST") NOT NULL DEFAULT 'POST',
|
method ENUM("GET","POST") NOT NULL DEFAULT 'POST',
|
||||||
`username` VARCHAR(255),
|
username VARCHAR(255),
|
||||||
`password` VARCHAR(255),
|
password VARCHAR(255),
|
||||||
PRIMARY KEY (`webhook_sid`)
|
PRIMARY KEY (webhook_sid)
|
||||||
) COMMENT='An HTTP callback';
|
) COMMENT='An HTTP callback';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `lcr_carrier_set_entry`
|
CREATE TABLE sip_gateways
|
||||||
(
|
(
|
||||||
`lcr_carrier_set_entry_sid` CHAR(36),
|
sip_gateway_sid CHAR(36),
|
||||||
`workload` INTEGER NOT NULL DEFAULT 1 COMMENT 'represents a proportion of traffic to send through the associated carrier; can be used for load balancing traffic across carriers with a common priority for a destination',
|
ipv4 VARCHAR(128) NOT NULL COMMENT 'ip address or DNS name of the gateway. For gateways providing inbound calling service, ip address is required.',
|
||||||
`lcr_route_sid` CHAR(36) NOT NULL,
|
port INTEGER NOT NULL DEFAULT 5060 COMMENT 'sip signaling port',
|
||||||
`voip_carrier_sid` CHAR(36) NOT NULL,
|
inbound BOOLEAN NOT NULL COMMENT 'if true, whitelist this IP to allow inbound calls from the gateway',
|
||||||
`priority` INTEGER NOT NULL DEFAULT 0 COMMENT 'lower priority carriers are attempted first',
|
outbound BOOLEAN NOT NULL COMMENT 'if true, include in least-cost routing when placing calls to the PSTN',
|
||||||
PRIMARY KEY (`lcr_carrier_set_entry_sid`)
|
voip_carrier_sid CHAR(36) NOT NULL,
|
||||||
) COMMENT='An entry in the LCR routing list';
|
is_active BOOLEAN NOT NULL DEFAULT 1,
|
||||||
|
PRIMARY KEY (sip_gateway_sid)
|
||||||
CREATE TABLE IF NOT EXISTS `sip_gateways`
|
|
||||||
(
|
|
||||||
`sip_gateway_sid` CHAR(36),
|
|
||||||
`ipv4` VARCHAR(32) NOT NULL COMMENT 'ip address or DNS name of the gateway. For gateways providing inbound calling service, ip address is required.',
|
|
||||||
`port` INTEGER NOT NULL DEFAULT 5060 COMMENT 'sip signaling port',
|
|
||||||
`inbound` BOOLEAN NOT NULL COMMENT 'if true, whitelist this IP to allow inbound calls from the gateway',
|
|
||||||
`outbound` BOOLEAN NOT NULL COMMENT 'if true, include in least-cost routing when placing calls to the PSTN',
|
|
||||||
`voip_carrier_sid` CHAR(36) NOT NULL,
|
|
||||||
`is_active` BOOLEAN NOT NULL DEFAULT 1,
|
|
||||||
PRIMARY KEY (`sip_gateway_sid`)
|
|
||||||
) COMMENT='A whitelisted sip gateway used for origination/termination';
|
) COMMENT='A whitelisted sip gateway used for origination/termination';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `applications`
|
CREATE TABLE lcr_carrier_set_entry
|
||||||
(
|
(
|
||||||
`application_sid` CHAR(36) NOT NULL UNIQUE ,
|
lcr_carrier_set_entry_sid CHAR(36),
|
||||||
`name` VARCHAR(64) NOT NULL,
|
workload INTEGER NOT NULL DEFAULT 1 COMMENT 'represents a proportion of traffic to send through the associated carrier; can be used for load balancing traffic across carriers with a common priority for a destination',
|
||||||
`account_sid` CHAR(36) NOT NULL COMMENT 'account that this application belongs to',
|
lcr_route_sid CHAR(36) NOT NULL,
|
||||||
`call_hook_sid` CHAR(36) COMMENT 'webhook to call for inbound calls to phone numbers owned by this account',
|
voip_carrier_sid CHAR(36) NOT NULL,
|
||||||
`call_status_hook_sid` CHAR(36) COMMENT 'webhook to call for call status events',
|
priority INTEGER NOT NULL DEFAULT 0 COMMENT 'lower priority carriers are attempted first',
|
||||||
`speech_synthesis_vendor` VARCHAR(64) NOT NULL DEFAULT 'google',
|
PRIMARY KEY (lcr_carrier_set_entry_sid)
|
||||||
`speech_synthesis_voice` VARCHAR(64) NOT NULL DEFAULT 'en-US-Wavenet-C',
|
) COMMENT='An entry in the LCR routing list';
|
||||||
`speech_recognizer_vendor` VARCHAR(64) NOT NULL DEFAULT 'google',
|
|
||||||
`speech_recognizer_language` VARCHAR(64) NOT NULL DEFAULT 'en-US',
|
CREATE TABLE applications
|
||||||
PRIMARY KEY (`application_sid`)
|
(
|
||||||
|
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_status_hook_sid CHAR(36) COMMENT 'webhook to call for call status events',
|
||||||
|
speech_synthesis_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||||
|
speech_synthesis_language VARCHAR(12) NOT NULL DEFAULT 'en-US',
|
||||||
|
speech_synthesis_voice VARCHAR(64),
|
||||||
|
speech_recognizer_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||||
|
speech_recognizer_language VARCHAR(64) NOT NULL DEFAULT 'en-US',
|
||||||
|
PRIMARY KEY (application_sid)
|
||||||
) ENGINE=InnoDB COMMENT='A defined set of behaviors to be applied to phone calls ';
|
) ENGINE=InnoDB COMMENT='A defined set of behaviors to be applied to phone calls ';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `service_providers`
|
CREATE TABLE service_providers
|
||||||
(
|
(
|
||||||
`service_provider_sid` CHAR(36) NOT NULL UNIQUE ,
|
service_provider_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`name` VARCHAR(64) NOT NULL UNIQUE ,
|
name VARCHAR(64) NOT NULL UNIQUE ,
|
||||||
`description` VARCHAR(255),
|
description VARCHAR(255),
|
||||||
`root_domain` VARCHAR(128) UNIQUE ,
|
root_domain VARCHAR(128) UNIQUE ,
|
||||||
`registration_hook_sid` CHAR(36),
|
registration_hook_sid CHAR(36),
|
||||||
PRIMARY KEY (`service_provider_sid`)
|
ms_teams_fqdn VARCHAR(255),
|
||||||
|
PRIMARY KEY (service_provider_sid)
|
||||||
) ENGINE=InnoDB COMMENT='A partition of the platform used by one service provider';
|
) ENGINE=InnoDB COMMENT='A partition of the platform used by one service provider';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `accounts`
|
CREATE TABLE accounts
|
||||||
(
|
(
|
||||||
`account_sid` CHAR(36) NOT NULL UNIQUE ,
|
account_sid CHAR(36) NOT NULL UNIQUE ,
|
||||||
`name` VARCHAR(64) NOT NULL,
|
name VARCHAR(64) NOT NULL,
|
||||||
`sip_realm` VARCHAR(132) UNIQUE COMMENT 'sip domain that will be used for devices registering under this account',
|
sip_realm VARCHAR(132) UNIQUE COMMENT 'sip domain that will be used for devices registering under this account',
|
||||||
`service_provider_sid` CHAR(36) NOT NULL COMMENT 'service provider that owns the customer relationship with this account',
|
service_provider_sid CHAR(36) NOT NULL COMMENT 'service provider that owns the customer relationship with this account',
|
||||||
`registration_hook_sid` CHAR(36) COMMENT 'webhook to call when devices underr this account attempt to register',
|
registration_hook_sid CHAR(36) COMMENT 'webhook to call when devices underr this account attempt to register',
|
||||||
`device_calling_application_sid` CHAR(36) COMMENT 'application to use for outbound calling from an account',
|
device_calling_application_sid CHAR(36) COMMENT 'application to use for outbound calling from an account',
|
||||||
`is_active` BOOLEAN NOT NULL DEFAULT true,
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||||
PRIMARY KEY (`account_sid`)
|
PRIMARY KEY (account_sid)
|
||||||
) ENGINE=InnoDB COMMENT='An enterprise that uses the platform for comm services';
|
) ENGINE=InnoDB COMMENT='An enterprise that uses the platform for comm services';
|
||||||
|
|
||||||
CREATE INDEX `call_routes_call_route_sid_idx` ON `call_routes` (`call_route_sid`);
|
CREATE INDEX call_route_sid_idx ON call_routes (call_route_sid);
|
||||||
ALTER TABLE `call_routes` ADD FOREIGN KEY account_sid_idxfk (`account_sid`) REFERENCES `accounts` (`account_sid`);
|
ALTER TABLE call_routes ADD FOREIGN KEY account_sid_idxfk (account_sid) REFERENCES accounts (account_sid);
|
||||||
|
|
||||||
ALTER TABLE `call_routes` ADD FOREIGN KEY application_sid_idxfk (`application_sid`) REFERENCES `applications` (`application_sid`);
|
ALTER TABLE call_routes ADD FOREIGN KEY application_sid_idxfk (application_sid) REFERENCES applications (application_sid);
|
||||||
|
|
||||||
CREATE INDEX `api_keys_api_key_sid_idx` ON `api_keys` (`api_key_sid`);
|
CREATE INDEX ms_teams_tenant_sid_idx ON ms_teams_tenants (ms_teams_tenant_sid);
|
||||||
CREATE INDEX `api_keys_account_sid_idx` ON `api_keys` (`account_sid`);
|
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY service_provider_sid_idxfk (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||||
ALTER TABLE `api_keys` ADD FOREIGN KEY account_sid_idxfk_1 (`account_sid`) REFERENCES `accounts` (`account_sid`);
|
|
||||||
|
|
||||||
CREATE INDEX `api_keys_service_provider_sid_idx` ON `api_keys` (`service_provider_sid`);
|
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY account_sid_idxfk_1 (account_sid) REFERENCES accounts (account_sid);
|
||||||
ALTER TABLE `api_keys` ADD FOREIGN KEY service_provider_sid_idxfk (`service_provider_sid`) REFERENCES `service_providers` (`service_provider_sid`);
|
|
||||||
|
|
||||||
CREATE INDEX `voip_carriers_voip_carrier_sid_idx` ON `voip_carriers` (`voip_carrier_sid`);
|
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY application_sid_idxfk_1 (application_sid) REFERENCES applications (application_sid);
|
||||||
CREATE INDEX `voip_carriers_name_idx` ON `voip_carriers` (`name`);
|
|
||||||
ALTER TABLE `voip_carriers` ADD FOREIGN KEY account_sid_idxfk_2 (`account_sid`) REFERENCES `accounts` (`account_sid`);
|
|
||||||
|
|
||||||
ALTER TABLE `voip_carriers` 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 `phone_numbers_phone_number_sid_idx` ON `phone_numbers` (`phone_number_sid`);
|
CREATE INDEX service_provider_sid_idx ON api_keys (service_provider_sid);
|
||||||
CREATE INDEX `phone_numbers_voip_carrier_sid_idx` ON `phone_numbers` (`voip_carrier_sid`);
|
ALTER TABLE api_keys ADD FOREIGN KEY service_provider_sid_idxfk_1 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||||
ALTER TABLE `phone_numbers` ADD FOREIGN KEY voip_carrier_sid_idxfk (`voip_carrier_sid`) REFERENCES `voip_carriers` (`voip_carrier_sid`);
|
|
||||||
|
|
||||||
ALTER TABLE `phone_numbers` ADD FOREIGN KEY account_sid_idxfk_3 (`account_sid`) REFERENCES `accounts` (`account_sid`);
|
CREATE INDEX sbc_addresses_idx_host_port ON sbc_addresses (ipv4,port);
|
||||||
|
|
||||||
ALTER TABLE `phone_numbers` ADD FOREIGN KEY application_sid_idxfk_2 (`application_sid`) REFERENCES `applications` (`application_sid`);
|
CREATE INDEX sbc_address_sid_idx ON sbc_addresses (sbc_address_sid);
|
||||||
|
CREATE INDEX service_provider_sid_idx ON sbc_addresses (service_provider_sid);
|
||||||
|
ALTER TABLE sbc_addresses ADD FOREIGN KEY service_provider_sid_idxfk_2 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||||
|
|
||||||
CREATE INDEX `webhooks_webhook_sid_idx` ON `webhooks` (`webhook_sid`);
|
CREATE INDEX user_sid_idx ON users (user_sid);
|
||||||
ALTER TABLE `lcr_carrier_set_entry` ADD FOREIGN KEY lcr_route_sid_idxfk (`lcr_route_sid`) REFERENCES `lcr_routes` (`lcr_route_sid`);
|
CREATE INDEX name_idx ON users (name);
|
||||||
|
CREATE INDEX voip_carrier_sid_idx ON voip_carriers (voip_carrier_sid);
|
||||||
|
CREATE INDEX name_idx ON voip_carriers (name);
|
||||||
|
ALTER TABLE voip_carriers ADD FOREIGN KEY account_sid_idxfk_3 (account_sid) REFERENCES accounts (account_sid);
|
||||||
|
|
||||||
ALTER TABLE `lcr_carrier_set_entry` ADD FOREIGN KEY voip_carrier_sid_idxfk_1 (`voip_carrier_sid`) REFERENCES `voip_carriers` (`voip_carrier_sid`);
|
ALTER TABLE voip_carriers ADD FOREIGN KEY application_sid_idxfk_2 (application_sid) REFERENCES applications (application_sid);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX `sip_gateways_sip_gateway_idx_hostport` ON `sip_gateways` (`ipv4`,`port`);
|
CREATE INDEX phone_number_sid_idx ON phone_numbers (phone_number_sid);
|
||||||
|
CREATE INDEX voip_carrier_sid_idx ON phone_numbers (voip_carrier_sid);
|
||||||
|
ALTER TABLE phone_numbers ADD FOREIGN KEY voip_carrier_sid_idxfk (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||||
|
|
||||||
ALTER TABLE `sip_gateways` ADD FOREIGN KEY voip_carrier_sid_idxfk_2 (`voip_carrier_sid`) REFERENCES `voip_carriers` (`voip_carrier_sid`);
|
ALTER TABLE phone_numbers ADD FOREIGN KEY account_sid_idxfk_4 (account_sid) REFERENCES accounts (account_sid);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX `applications_idx_name` ON `applications` (`account_sid`,`name`);
|
ALTER TABLE phone_numbers ADD FOREIGN KEY application_sid_idxfk_3 (application_sid) REFERENCES applications (application_sid);
|
||||||
|
|
||||||
CREATE INDEX `applications_application_sid_idx` ON `applications` (`application_sid`);
|
CREATE INDEX webhook_sid_idx ON webhooks (webhook_sid);
|
||||||
CREATE INDEX `applications_name_idx` ON `applications` (`name`);
|
CREATE UNIQUE INDEX sip_gateway_idx_hostport ON sip_gateways (ipv4,port);
|
||||||
CREATE INDEX `applications_account_sid_idx` ON `applications` (`account_sid`);
|
|
||||||
ALTER TABLE `applications` ADD FOREIGN KEY account_sid_idxfk_4 (`account_sid`) REFERENCES `accounts` (`account_sid`);
|
|
||||||
|
|
||||||
ALTER TABLE `applications` ADD FOREIGN KEY call_hook_sid_idxfk (`call_hook_sid`) REFERENCES `webhooks` (`webhook_sid`);
|
ALTER TABLE sip_gateways ADD FOREIGN KEY voip_carrier_sid_idxfk_1 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||||
|
|
||||||
ALTER TABLE `applications` ADD FOREIGN KEY call_status_hook_sid_idxfk (`call_status_hook_sid`) REFERENCES `webhooks` (`webhook_sid`);
|
ALTER TABLE lcr_carrier_set_entry ADD FOREIGN KEY lcr_route_sid_idxfk (lcr_route_sid) REFERENCES lcr_routes (lcr_route_sid);
|
||||||
|
|
||||||
CREATE INDEX `service_providers_service_provider_sid_idx` ON `service_providers` (`service_provider_sid`);
|
ALTER TABLE lcr_carrier_set_entry ADD FOREIGN KEY voip_carrier_sid_idxfk_2 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||||
CREATE INDEX `service_providers_name_idx` ON `service_providers` (`name`);
|
|
||||||
CREATE INDEX `service_providers_root_domain_idx` ON `service_providers` (`root_domain`);
|
|
||||||
ALTER TABLE `service_providers` ADD FOREIGN KEY registration_hook_sid_idxfk (`registration_hook_sid`) REFERENCES `webhooks` (`webhook_sid`);
|
|
||||||
|
|
||||||
CREATE INDEX `accounts_account_sid_idx` ON `accounts` (`account_sid`);
|
CREATE UNIQUE INDEX applications_idx_name ON applications (account_sid,name);
|
||||||
CREATE INDEX `accounts_name_idx` ON `accounts` (`name`);
|
|
||||||
CREATE INDEX `accounts_sip_realm_idx` ON `accounts` (`sip_realm`);
|
|
||||||
CREATE INDEX `accounts_service_provider_sid_idx` ON `accounts` (`service_provider_sid`);
|
|
||||||
ALTER TABLE `accounts` ADD FOREIGN KEY service_provider_sid_idxfk_1 (`service_provider_sid`) REFERENCES `service_providers` (`service_provider_sid`);
|
|
||||||
|
|
||||||
ALTER TABLE `accounts` ADD FOREIGN KEY registration_hook_sid_idxfk_1 (`registration_hook_sid`) REFERENCES `webhooks` (`webhook_sid`);
|
CREATE INDEX application_sid_idx ON applications (application_sid);
|
||||||
|
CREATE INDEX account_sid_idx ON applications (account_sid);
|
||||||
|
ALTER TABLE applications ADD FOREIGN KEY account_sid_idxfk_5 (account_sid) REFERENCES accounts (account_sid);
|
||||||
|
|
||||||
ALTER TABLE `accounts` ADD FOREIGN KEY device_calling_application_sid_idxfk (`device_calling_application_sid`) REFERENCES `applications` (`application_sid`);
|
ALTER TABLE applications ADD FOREIGN KEY call_hook_sid_idxfk (call_hook_sid) REFERENCES webhooks (webhook_sid);
|
||||||
|
|
||||||
|
ALTER TABLE applications ADD FOREIGN KEY call_status_hook_sid_idxfk (call_status_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);
|
||||||
|
ALTER TABLE service_providers ADD FOREIGN KEY registration_hook_sid_idxfk (registration_hook_sid) REFERENCES webhooks (webhook_sid);
|
||||||
|
|
||||||
|
CREATE INDEX account_sid_idx ON accounts (account_sid);
|
||||||
|
CREATE INDEX sip_realm_idx ON accounts (sip_realm);
|
||||||
|
CREATE INDEX service_provider_sid_idx ON accounts (service_provider_sid);
|
||||||
|
ALTER TABLE accounts ADD FOREIGN KEY service_provider_sid_idxfk_3 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user