mirror of
https://github.com/jambonz/sbc-inbound.git
synced 2025-12-19 04:37:43 +00:00
removed config in favor of env vars
This commit is contained in:
55
app.js
55
app.js
@@ -1,11 +1,45 @@
|
||||
const assert = require('assert');
|
||||
assert.ok(process.env.JAMBONES_MYSQL_HOST &&
|
||||
process.env.JAMBONES_MYSQL_USER &&
|
||||
process.env.JAMBONES_MYSQL_PASSWORD &&
|
||||
process.env.JAMBONES_MYSQL_DATABASE, 'missing JAMBONES_MYSQL_XXX env vars');
|
||||
assert.ok(process.env.JAMBONES_REDIS_HOST, 'missing JAMBONES_REDIS_HOST env var');
|
||||
assert.ok(process.env.DRACHTIO_PORT || process.env.DRACHTIO_HOST, 'missing DRACHTIO_PORT env var');
|
||||
assert.ok(process.env.DRACHTIO_SECRET, 'missing DRACHTIO_SECRET env var');
|
||||
assert.ok(process.env.JAMBONES_RTPENGINES, 'missing JAMBONES_RTPENGINES env var');
|
||||
assert.ok(process.env.JAMBONES_FEATURE_SERVERS, 'missing JAMBONES_FEATURE_SERVERS env var');
|
||||
|
||||
const Srf = require('drachtio-srf');
|
||||
const srf = new Srf();
|
||||
const config = require('config');
|
||||
const logger = require('pino')(config.get('logging'));
|
||||
const opts = Object.assign({
|
||||
timestamp: () => {return `, "time": "${new Date().toISOString()}"`;}
|
||||
}, {level: process.env.JAMBONES_LOGLEVEL || 'info'});
|
||||
const logger = require('pino')(opts);
|
||||
const {
|
||||
lookupAuthHook,
|
||||
lookupSipGatewayBySignalingAddress
|
||||
} = require('jambonz-db-helpers')(config.get('mysql'), logger);
|
||||
} = require('jambonz-db-helpers')({
|
||||
host: process.env.JAMBONES_MYSQL_HOST,
|
||||
user: process.env.JAMBONES_MYSQL_USER,
|
||||
password: process.env.JAMBONES_MYSQL_PASSWORD,
|
||||
database: process.env.JAMBONES_MYSQL_DATABASE,
|
||||
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
||||
}, logger);
|
||||
|
||||
// parse rtpengines
|
||||
srf.locals.rtpEngines = process.env.JAMBONES_RTPENGINES
|
||||
.split(',')
|
||||
.map((hp) => {
|
||||
const arr = /^(.*):(.*)$/.exec(hp.trim());
|
||||
if (arr) return {host: arr[1], port: parseInt(arr[2])};
|
||||
});
|
||||
assert.ok(srf.locals.rtpEngines.length > 0, 'JAMBONES_RTPENGINES must be an array host:port addresses');
|
||||
|
||||
// parse application servers
|
||||
srf.locals.featureServers = process.env.JAMBONES_FEATURE_SERVERS
|
||||
.split(',')
|
||||
.map((hp) => hp.trim());
|
||||
|
||||
srf.locals.dbHelpers = {
|
||||
lookupAuthHook,
|
||||
lookupSipGatewayBySignalingAddress
|
||||
@@ -13,23 +47,14 @@ srf.locals.dbHelpers = {
|
||||
const {challengeDeviceCalls} = require('./lib/middleware')(srf, logger);
|
||||
const CallSession = require('./lib/call-session');
|
||||
|
||||
// disable logging in test mode
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
const noop = () => {};
|
||||
logger.info = logger.debug = noop;
|
||||
logger.child = () => {return {info: noop, error: noop, debug: noop};};
|
||||
}
|
||||
|
||||
// config dictates whether to use outbound or inbound connections
|
||||
if (config.has('drachtio.host')) {
|
||||
srf.connect(config.get('drachtio'));
|
||||
if (process.env.DRACHTIO_HOST) {
|
||||
srf.connect({host: process.env.DRACHTIO_HOST, port: process.env.DRACHTIO_PORT, secret: process.env.DRACHTIO_SECRET });
|
||||
srf.on('connect', (err, hp) => {
|
||||
logger.info(`connected to drachtio listening on ${hp}`);
|
||||
});
|
||||
}
|
||||
else {
|
||||
logger.info(`listening for drachtio server traffic on ${JSON.stringify(config.get('drachtio'))}`);
|
||||
srf.listen(config.get('drachtio'));
|
||||
srf.listen({host: process.env.DRACHTIO_PORT, secret: process.env.DRACHTIO_SECRET});
|
||||
}
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
srf.on('error', (err) => {
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"drachtio": {
|
||||
"port": 3003,
|
||||
"secret": "cymru"
|
||||
},
|
||||
"rtpengine": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 22222
|
||||
},
|
||||
"logging": {
|
||||
"level": "info"
|
||||
},
|
||||
"mysql": {
|
||||
"host": "localhost",
|
||||
"user": "jambones",
|
||||
"password": "jambones",
|
||||
"database": "jambones"
|
||||
},
|
||||
"trunks": {
|
||||
"appserver": ["172.38.0.11"]
|
||||
},
|
||||
"transcoding": {
|
||||
"rtpCharacteristics" : {
|
||||
"transport protocol": "RTP/AVP",
|
||||
"DTLS": "off",
|
||||
"SDES": "off",
|
||||
"ICE": "remove",
|
||||
"rtcp-mux": ["demux"]
|
||||
},
|
||||
"srtpCharacteristics": {
|
||||
"transport-protocol": "UDP/TLS/RTP/SAVPF",
|
||||
"ICE": "force",
|
||||
"SDES": "off",
|
||||
"flags": ["generate mid", "SDES-no"],
|
||||
"rtcp-mux": ["require"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"drachtio": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 9060,
|
||||
"secret": "cymru"
|
||||
},
|
||||
"rtpengine": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 12222
|
||||
},
|
||||
"logging": {
|
||||
"level": "debug"
|
||||
},
|
||||
"mysql": {
|
||||
"host": "localhost",
|
||||
"user": "jambones_test",
|
||||
"password": "jambones_test",
|
||||
"database": "jambones_test"
|
||||
},
|
||||
"trunks": {
|
||||
"appserver": ["172.38.0.11"]
|
||||
},
|
||||
"transcoding": {
|
||||
"rtpCharacteristics" : {
|
||||
"transport protocol": "RTP/AVP",
|
||||
"DTLS": "off",
|
||||
"SDES": "off",
|
||||
"ICE": "remove",
|
||||
"rtcp-mux": ["demux"]
|
||||
},
|
||||
"srtpCharacteristics": {
|
||||
"transport-protocol": "UDP/TLS/RTP/SAVPF",
|
||||
"ICE": "force",
|
||||
"SDES": "off",
|
||||
"flags": ["generate mid", "SDES-no"],
|
||||
"rtcp-mux": ["require"]
|
||||
}
|
||||
}
|
||||
}
|
||||
7
data/rtp-transcoding.json
Normal file
7
data/rtp-transcoding.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"transport protocol": "RTP/AVP",
|
||||
"DTLS": "off",
|
||||
"SDES": "off",
|
||||
"ICE": "remove",
|
||||
"rtcp-mux": ["demux"]
|
||||
}
|
||||
7
data/srtp-transcoding.json
Normal file
7
data/srtp-transcoding.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"transport-protocol": "UDP/TLS/RTP/SAVPF",
|
||||
"ICE": "force",
|
||||
"SDES": "off",
|
||||
"flags": ["generate mid", "SDES-no"],
|
||||
"rtcp-mux": ["require"]
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
const Emitter = require('events');
|
||||
const config = require('config');
|
||||
const Client = require('rtpengine-client').Client ;
|
||||
const rtpengine = new Client();
|
||||
const offer = rtpengine.offer.bind(rtpengine, config.get('rtpengine'));
|
||||
const answer = rtpengine.answer.bind(rtpengine, config.get('rtpengine'));
|
||||
const del = rtpengine.delete.bind(rtpengine, config.get('rtpengine'));
|
||||
const {getAppserver, isWSS, makeRtpEngineOpts} = require('./utils');
|
||||
const {forwardInDialogRequests} = require('drachtio-fn-b2b-sugar');
|
||||
const {parseUri, SipError} = require('drachtio-srf');
|
||||
@@ -17,13 +13,19 @@ class CallSession extends Emitter {
|
||||
this.res = res;
|
||||
this.srf = req.srf;
|
||||
this.logger = logger.child({callId: req.get('Call-ID')});
|
||||
|
||||
// TODO: we always using the first rtpengine here
|
||||
// we should be load balancing, and doing some form of health checking
|
||||
this.offer = rtpengine.offer.bind(rtpengine, this.srf.locals.rtpEngines[0]);
|
||||
this.answer = rtpengine.answer.bind(rtpengine, this.srf.locals.rtpEngines[0]);
|
||||
this.del = rtpengine.delete.bind(rtpengine, this.srf.locals.rtpEngines[0]);
|
||||
}
|
||||
|
||||
async connect() {
|
||||
this.rtpEngineOpts = makeRtpEngineOpts(this.req, isWSS(this.req), false);
|
||||
this.rtpEngineResource = {destroy: del.bind(rtpengine, this.rtpEngineOpts.common)};
|
||||
this.rtpEngineResource = {destroy: this.del.bind(rtpengine, this.rtpEngineOpts.common)};
|
||||
const obj = parseUri(this.req.uri);
|
||||
const appServer = getAppserver();
|
||||
const appServer = getAppserver(this.srf);
|
||||
let proxy, host, uri;
|
||||
|
||||
// replace host part of uri if its an ipv4 address, leave it otherwise
|
||||
@@ -41,7 +43,7 @@ class CallSession extends Emitter {
|
||||
try {
|
||||
// rtpengine 'offer'
|
||||
debug('sending offer command to rtpengine');
|
||||
const response = await offer(this.rtpEngineOpts.offer);
|
||||
const response = await this.offer(this.rtpEngineOpts.offer);
|
||||
debug(`response from rtpengine to offer ${JSON.stringify(response)}`);
|
||||
if ('ok' !== response.result) {
|
||||
this.logger.error(`rtpengine offer failed with ${JSON.stringify(response)}`);
|
||||
@@ -77,7 +79,7 @@ class CallSession extends Emitter {
|
||||
localSdpA: async(sdp, res) => {
|
||||
const opts = Object.assign({sdp, 'to-tag': res.getParsedHeader('To').params.tag},
|
||||
this.rtpEngineOpts.answer);
|
||||
const response = await answer(opts);
|
||||
const response = await this.answer(opts);
|
||||
if ('ok' !== response.result) {
|
||||
this.logger.error(`rtpengine answer failed with ${JSON.stringify(response)}`);
|
||||
throw new Error('rtpengine failed: answer');
|
||||
@@ -123,7 +125,7 @@ class CallSession extends Emitter {
|
||||
|
||||
async _onReinvite(dlg, req, res) {
|
||||
try {
|
||||
let response = await offer(Object.assign({sdp: req.body}, this.rtpEngineOpts.offer));
|
||||
let response = await this.offer(Object.assign({sdp: req.body}, this.rtpEngineOpts.offer));
|
||||
if ('ok' !== response.result) {
|
||||
res.send(488);
|
||||
throw new Error(`_onReinvite: rtpengine failed: offer: ${JSON.stringify(response)}`);
|
||||
@@ -131,7 +133,7 @@ class CallSession extends Emitter {
|
||||
const sdp = await dlg.other.modify(response.sdp);
|
||||
const opts = Object.assign({sdp, 'to-tag': res.getParsedHeader('To').params.tag},
|
||||
this.rtpEngineOpts.answer);
|
||||
response = await answer(opts);
|
||||
response = await this.answer(opts);
|
||||
if ('ok' !== response.result) {
|
||||
res.send(488);
|
||||
throw new Error(`_onReinvite: rtpengine failed: ${JSON.stringify(response)}`);
|
||||
|
||||
11
lib/utils.js
11
lib/utils.js
@@ -1,20 +1,19 @@
|
||||
const config = require('config');
|
||||
const rtpCharacteristics = require('../data/rtp-transcoding');
|
||||
const srtpCharacteristics = require('../data/srtp-transcoding');
|
||||
let idx = 0;
|
||||
|
||||
function isWSS(req) {
|
||||
return req.getParsedHeader('Via')[0].protocol.toLowerCase().startsWith('ws');
|
||||
}
|
||||
|
||||
function getAppserver() {
|
||||
const len = config.get('trunks.appserver').length;
|
||||
return config.get('trunks.appserver')[ idx++ % len];
|
||||
function getAppserver(srf) {
|
||||
const len = srf.locals.featureServers.length;
|
||||
return srf.locals.featureServers[ idx++ % len];
|
||||
}
|
||||
|
||||
function makeRtpEngineOpts(req, srcIsUsingSrtp, dstIsUsingSrtp) {
|
||||
const from = req.getParsedHeader('from');
|
||||
const common = {'call-id': req.get('Call-ID'), 'from-tag': from.params.tag};
|
||||
const rtpCharacteristics = config.get('transcoding.rtpCharacteristics');
|
||||
const srtpCharacteristics = config.get('transcoding.srtpCharacteristics');
|
||||
return {
|
||||
common,
|
||||
offer: Object.assign({'sdp': req.body, 'replace': ['origin', 'session-connection']}, common,
|
||||
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sbc-inbound",
|
||||
"version": "0.1.3",
|
||||
"version": "0.2.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -737,9 +737,9 @@
|
||||
}
|
||||
},
|
||||
"drachtio-srf": {
|
||||
"version": "4.4.27",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.27.tgz",
|
||||
"integrity": "sha512-jMtIHaJCQrkAPdlPABbDLDeOXzPea+m7HCTQMeFV6kAD5dMEAfgrAq5+BfSPhidjySuI6954FvmQuWZo7aRSlw==",
|
||||
"version": "4.4.28",
|
||||
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.28.tgz",
|
||||
"integrity": "sha512-gY/wmH6JFmeEv2/jhwFbky1NYUmDwgIJzjNeGlDiAkQEA6GgcI/CFi5RRHAUzghpczTwXQNDXpARPB8QDWX1JA==",
|
||||
"requires": {
|
||||
"async": "^1.4.2",
|
||||
"debug": "^3.1.0",
|
||||
@@ -1758,9 +1758,9 @@
|
||||
}
|
||||
},
|
||||
"jambonz-db-helpers": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/jambonz-db-helpers/-/jambonz-db-helpers-0.2.4.tgz",
|
||||
"integrity": "sha512-qfMKvXv//UDGFveOmeC3Xq2jMvTP7Y1P4F3EPf7VAgD10/ipozLRdEx+o3HlyF9wOeP3syha9ofpnel8VYLGLA==",
|
||||
"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"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sbc-inbound",
|
||||
"version": "0.1.3",
|
||||
"version": "0.2.0",
|
||||
"main": "app.js",
|
||||
"engines": {
|
||||
"node": ">= 10.16.0"
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app",
|
||||
"test": "NODE_ENV=test node test/ | ./node_modules/.bin/tap-spec",
|
||||
"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",
|
||||
"coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test",
|
||||
"jslint": "eslint app.js lib"
|
||||
},
|
||||
@@ -28,8 +28,8 @@
|
||||
"config": "^3.2.4",
|
||||
"debug": "^4.1.1",
|
||||
"drachtio-fn-b2b-sugar": "0.0.12",
|
||||
"drachtio-srf": "^4.4.27",
|
||||
"jambonz-db-helpers": "^0.2.4",
|
||||
"drachtio-srf": "^4.4.28",
|
||||
"jambonz-db-helpers": "^0.3.2",
|
||||
"jambonz-http-authenticator": "0.0.7",
|
||||
"pino": "^5.14.0",
|
||||
"rtpengine-client": "^0.0.8"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* SQLEditor (MySQL (2))*/
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
DROP TABLE IF EXISTS `call_routes`;
|
||||
|
||||
@@ -15,14 +16,16 @@ 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 IF NOT EXISTS `call_routes`
|
||||
(
|
||||
`call_route_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
@@ -61,26 +64,26 @@ CREATE TABLE IF NOT EXISTS `voip_carriers`
|
||||
PRIMARY KEY (`voip_carrier_sid`)
|
||||
) ENGINE=InnoDB COMMENT='A Carrier or customer PBX that can send or receive calls';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `webhooks`
|
||||
(
|
||||
`webhook_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
`url` VARCHAR(255) NOT NULL,
|
||||
`method` ENUM("get","post") NOT NULL DEFAULT 'post',
|
||||
`username` VARCHAR(255),
|
||||
`password` VARCHAR(255),
|
||||
PRIMARY KEY (`webhook_sid`)
|
||||
) COMMENT='An HTTP callback';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `phone_numbers`
|
||||
(
|
||||
`phone_number_sid` CHAR(36) UNIQUE ,
|
||||
`number` VARCHAR(255) NOT NULL UNIQUE ,
|
||||
`number` VARCHAR(32) NOT NULL UNIQUE ,
|
||||
`voip_carrier_sid` CHAR(36) NOT NULL,
|
||||
`account_sid` CHAR(36),
|
||||
`application_sid` CHAR(36),
|
||||
PRIMARY KEY (`phone_number_sid`)
|
||||
) ENGINE=InnoDB COMMENT='A phone number that has been assigned to an account';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `webhooks`
|
||||
(
|
||||
`webhook_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
`url` VARCHAR(1024) NOT NULL,
|
||||
`method` ENUM("GET","POST") NOT NULL DEFAULT 'POST',
|
||||
`username` VARCHAR(255),
|
||||
`password` VARCHAR(255),
|
||||
PRIMARY KEY (`webhook_sid`)
|
||||
) COMMENT='An HTTP callback';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `lcr_carrier_set_entry`
|
||||
(
|
||||
`lcr_carrier_set_entry_sid` CHAR(36),
|
||||
@@ -106,7 +109,7 @@ PRIMARY KEY (`sip_gateway_sid`)
|
||||
CREATE TABLE IF NOT EXISTS `applications`
|
||||
(
|
||||
`application_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`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',
|
||||
@@ -122,7 +125,7 @@ CREATE TABLE IF NOT EXISTS `service_providers`
|
||||
`service_provider_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
`name` VARCHAR(64) NOT NULL UNIQUE ,
|
||||
`description` VARCHAR(255),
|
||||
`root_domain` VARCHAR(255) UNIQUE ,
|
||||
`root_domain` VARCHAR(128) UNIQUE ,
|
||||
`registration_hook_sid` CHAR(36),
|
||||
PRIMARY KEY (`service_provider_sid`)
|
||||
) ENGINE=InnoDB COMMENT='A partition of the platform used by one service provider';
|
||||
@@ -130,11 +133,11 @@ PRIMARY KEY (`service_provider_sid`)
|
||||
CREATE TABLE IF NOT EXISTS `accounts`
|
||||
(
|
||||
`account_sid` CHAR(36) NOT NULL UNIQUE ,
|
||||
`name` VARCHAR(255) 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',
|
||||
`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',
|
||||
`device_calling_hook_sid` CHAR(36) COMMENT 'webhook to call when devices under this account place outbound calls',
|
||||
`device_calling_application_sid` CHAR(36) COMMENT 'application to use for outbound calling from an account',
|
||||
`is_active` BOOLEAN NOT NULL DEFAULT true,
|
||||
PRIMARY KEY (`account_sid`)
|
||||
) ENGINE=InnoDB COMMENT='An enterprise that uses the platform for comm services';
|
||||
@@ -157,7 +160,6 @@ ALTER TABLE `voip_carriers` ADD FOREIGN KEY account_sid_idxfk_2 (`account_sid`)
|
||||
|
||||
ALTER TABLE `voip_carriers` ADD FOREIGN KEY application_sid_idxfk_1 (`application_sid`) REFERENCES `applications` (`application_sid`);
|
||||
|
||||
CREATE INDEX `webhooks_webhook_sid_idx` ON `webhooks` (`webhook_sid`);
|
||||
CREATE INDEX `phone_numbers_phone_number_sid_idx` ON `phone_numbers` (`phone_number_sid`);
|
||||
CREATE INDEX `phone_numbers_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`);
|
||||
@@ -166,6 +168,7 @@ ALTER TABLE `phone_numbers` ADD FOREIGN KEY account_sid_idxfk_3 (`account_sid`)
|
||||
|
||||
ALTER TABLE `phone_numbers` ADD FOREIGN KEY application_sid_idxfk_2 (`application_sid`) REFERENCES `applications` (`application_sid`);
|
||||
|
||||
CREATE INDEX `webhooks_webhook_sid_idx` ON `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`);
|
||||
|
||||
ALTER TABLE `lcr_carrier_set_entry` ADD FOREIGN KEY voip_carrier_sid_idxfk_1 (`voip_carrier_sid`) REFERENCES `voip_carriers` (`voip_carrier_sid`);
|
||||
@@ -198,4 +201,4 @@ ALTER TABLE `accounts` ADD FOREIGN KEY service_provider_sid_idxfk_1 (`service_pr
|
||||
|
||||
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_hook_sid_idxfk (`device_calling_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