removed config in favor of env vars

This commit is contained in:
Dave Horton
2020-02-15 18:59:42 -05:00
parent fb969379ed
commit 4fc640edc1
10 changed files with 131 additions and 316 deletions

57
app.js
View File

@@ -1,42 +1,59 @@
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');
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 {route, setLogger} = require('./lib/middleware');
const CallSession = require('./lib/call-session');
const {performLcr} = require('jambonz-db-helpers')(config.get('mysql'), logger);
const {performLcr} = 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);
srf.locals.dbHelpers = {performLcr};
const debug = require('debug')('jambonz:sbc-outbound');
debug(typeof performLcr);
// 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};};
}
// 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');
// 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) => {
debug(`connected to drachtio at ${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) => {
logger.error(err, 'Error connecting to drachtio');
logger.info(err, 'Error connecting to drachtio');
});
}
srf.use('invite', [setLogger(logger), route(config.get('redis'))]);
srf.use('invite', [setLogger(logger), route({
host: process.env.JAMBONES_REDIS_HOST,
port: process.env.JAMBONES_REDIS_PORT || 6379
})]);
srf.invite((req, res) => {
debug('got invite');
const session = new CallSession(logger, req, res);
session.connect();
});

View File

@@ -1,39 +0,0 @@
{
"drachtio": {
"port": 3002,
"secret": "cymru"
},
"rtpengine": {
"host": "127.0.0.1",
"port": 22222
},
"redis": {
"port": 6379,
"host": "127.0.0.1"
},
"logging": {
"level": "info"
},
"mysql": {
"host": "localhost",
"user": "jambones",
"password": "jambones",
"database": "jambones"
},
"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"]
}
}
}

View File

@@ -1,40 +0,0 @@
{
"drachtio": {
"host": "127.0.0.1",
"port": 9060,
"secret": "cymru"
},
"rtpengine": {
"host": "127.0.0.1",
"port": 12222
},
"redis": {
"port": 16379,
"host": "127.0.0.1"
},
"mysql": {
"host": "localhost",
"user": "jambones_test",
"password": "jambones_test",
"database": "jambones_test"
},
"logging": {
"level": "info"
},
"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"]
}
}
}

View File

@@ -0,0 +1,7 @@
{
"transport protocol": "RTP/AVP",
"DTLS": "off",
"SDES": "off",
"ICE": "remove",
"rtcp-mux": ["demux"]
}

View File

@@ -0,0 +1,7 @@
{
"transport-protocol": "UDP/TLS/RTP/SAVPF",
"ICE": "force",
"SDES": "off",
"flags": ["generate mid", "SDES-no"],
"rtcp-mux": ["require"]
}

View File

@@ -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 {makeRtpEngineOpts} = require('./utils');
const {forwardInDialogRequests} = require('drachtio-fn-b2b-sugar');
const {SipError} = require('drachtio-srf');
@@ -19,11 +15,17 @@ class CallSession extends Emitter {
this.performLcr = this.srf.locals.dbHelpers.performLcr;
this.logger = logger.child({callId: req.get('Call-ID')});
this.useWss = req.locals.registration && req.locals.registration.protocol === 'wss';
// 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, false, this.useWss);
this.rtpEngineResource = {destroy: del.bind(rtpengine, this.rtpEngineOpts.common)};
this.rtpEngineResource = {destroy: this.del.bind(rtpengine, this.rtpEngineOpts.common)};
let proxy, uris;
try {
@@ -56,7 +58,7 @@ class CallSession extends Emitter {
// 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)}`);
@@ -79,7 +81,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');
@@ -148,7 +150,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)}`);
@@ -156,7 +158,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)}`);

View File

@@ -1,11 +1,10 @@
const config = require('config');
const rtpCharacteristics = require('../data/rtp-transcoding');
const srtpCharacteristics = require('../data/srtp-transcoding');
const debug = require('debug')('jambonz:sbc-outbound');
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,

33
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "sbc-outbound",
"version": "0.2.0",
"version": "0.3.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -537,14 +537,6 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"config": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/config/-/config-3.2.4.tgz",
"integrity": "sha512-H1XIGfnU1EAkfjSLn9ZvYDRx9lOezDViuzLDgiJ/lMeqjYe3q6iQfpcLt2NInckJgpAeekbNhQkmnnbdEDs9rw==",
"requires": {
"json5": "^1.0.1"
}
},
"convert-source-map": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
@@ -749,9 +741,9 @@
}
},
"drachtio-srf": {
"version": "4.4.26",
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.26.tgz",
"integrity": "sha512-viEzAhJ2JenpUstXWvHXGpjZckcyfciadD1fG67JxmyvgDYn6RKNeHk/LPjeJUdRNg5z8yS6Lgx4jCtuBP1DJQ==",
"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",
@@ -1809,9 +1801,9 @@
}
},
"jambonz-db-helpers": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/jambonz-db-helpers/-/jambonz-db-helpers-0.2.0.tgz",
"integrity": "sha512-AykK4ICzUl5/LaNQGZdy8dlWuv8nOSSRVAqQDztJvdmJHyl4wTEC+///pKNgQlm+RX7R3vCV7dFCVoTHuIAx3A==",
"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"
@@ -1884,14 +1876,6 @@
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"requires": {
"minimist": "^1.2.0"
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -2068,7 +2052,8 @@
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"minipass": {
"version": "3.1.1",

View File

@@ -1,6 +1,6 @@
{
"name": "sbc-outbound",
"version": "0.2.0",
"version": "0.3.0",
"main": "app.js",
"engines": {
"node": ">= 8.10.0"
@@ -22,16 +22,15 @@
"description": "jambonz session border controller application for outbound calls",
"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 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": {
"config": "^3.2.4",
"debug": "^4.1.1",
"drachtio-fn-b2b-sugar": "^0.0.12",
"drachtio-srf": "^4.4.24",
"jambonz-db-helpers": "^0.2.0",
"drachtio-srf": "^4.4.28",
"jambonz-db-helpers": "^0.3.2",
"jambonz-mw-registrar": "^0.1.0",
"pino": "^5.14.0",
"rtpengine-client": "^0.0.8"

View File

@@ -1,26 +1,13 @@
/* SQLEditor (MySQL (2))*/
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `call_routes`;
DROP TABLE IF EXISTS `conference_participants`;
DROP TABLE IF EXISTS `conferences`;
DROP TABLE IF EXISTS `lcr_carrier_set_entry`;
DROP TABLE IF EXISTS `lcr_routes`;
DROP TABLE IF EXISTS `queue_members`;
DROP TABLE IF EXISTS `queues`;
DROP TABLE IF EXISTS `calls`;
DROP TABLE IF EXISTS `subscriptions`;
DROP TABLE IF EXISTS `registrations`;
DROP TABLE IF EXISTS `api_keys`;
DROP TABLE IF EXISTS `phone_numbers`;
@@ -29,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 ,
@@ -45,94 +34,16 @@ CREATE TABLE IF NOT EXISTS `call_routes`
`regex` VARCHAR(255) NOT NULL,
`application_sid` CHAR(36) NOT NULL,
PRIMARY KEY (`call_route_sid`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `conferences`
(
`id` INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE ,
`conference_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='An audio conference';
CREATE TABLE IF NOT EXISTS `conference_participants`
(
`conference_participant_sid` CHAR(36) NOT NULL UNIQUE ,
`call_sid` CHAR(36),
`conference_sid` CHAR(36) NOT NULL,
PRIMARY KEY (`conference_participant_sid`)
) ENGINE=InnoDB COMMENT='A relationship between a call and a conference that it is co';
) ENGINE=InnoDB COMMENT='a regex-based pattern match for call routing';
CREATE TABLE IF NOT EXISTS `lcr_routes`
(
`lcr_route_sid` CHAR(36),
`regex` VARCHAR(32) NOT NULL,
`regex` VARCHAR(32) NOT NULL COMMENT 'regex-based pattern match against dialed number, used for LCR routing of PSTN calls',
`description` VARCHAR(1024),
`priority` INTEGER NOT NULL UNIQUE ,
`priority` INTEGER NOT NULL UNIQUE COMMENT 'lower priority routes are attempted first',
PRIMARY KEY (`lcr_route_sid`)
);
CREATE TABLE IF NOT EXISTS `queues`
(
`id` INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE ,
`queue_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='A set of behaviors to be applied to parked calls';
CREATE TABLE IF NOT EXISTS `registrations`
(
`registration_sid` CHAR(36) NOT NULL UNIQUE ,
`username` VARCHAR(255) NOT NULL,
`domain` VARCHAR(255) NOT NULL,
`sip_contact` VARCHAR(255) NOT NULL,
`sip_user_agent` VARCHAR(255),
PRIMARY KEY (`registration_sid`)
) ENGINE=InnoDB COMMENT='An active sip registration';
CREATE TABLE IF NOT EXISTS `queue_members`
(
`queue_member_sid` CHAR(36) NOT NULL UNIQUE ,
`call_sid` CHAR(36),
`queue_sid` CHAR(36) NOT NULL,
`position` INTEGER,
PRIMARY KEY (`queue_member_sid`)
) ENGINE=InnoDB COMMENT='A relationship between a call and a queue that it is waiting';
CREATE TABLE IF NOT EXISTS `calls`
(
`call_sid` CHAR(36) NOT NULL UNIQUE ,
`parent_call_sid` CHAR(36),
`application_sid` CHAR(36),
`status_url` VARCHAR(255),
`time_start` DATETIME NOT NULL,
`time_alerting` DATETIME,
`time_answered` DATETIME,
`time_ended` DATETIME,
`direction` ENUM('inbound','outbound'),
`phone_number_sid` CHAR(36),
`inbound_user_sid` CHAR(36),
`outbound_user_sid` CHAR(36),
`calling_number` VARCHAR(255),
`called_number` VARCHAR(255),
`caller_name` VARCHAR(255),
`status` VARCHAR(255) NOT NULL COMMENT 'Possible values are queued, ringing, in-progress, completed, failed, busy and no-answer',
`sip_uri` VARCHAR(255) NOT NULL,
`sip_call_id` VARCHAR(255) NOT NULL,
`sip_cseq` INTEGER NOT NULL,
`sip_from_tag` VARCHAR(255) NOT NULL,
`sip_via_branch` VARCHAR(255) NOT NULL,
`sip_contact` VARCHAR(255),
`sip_final_status` INTEGER UNSIGNED,
`sdp_offer` VARCHAR(4096),
`sdp_answer` VARCHAR(4096),
`source_address` VARCHAR(255) NOT NULL,
`source_port` INTEGER UNSIGNED NOT NULL,
`dest_address` VARCHAR(255),
`dest_port` INTEGER UNSIGNED,
`url` VARCHAR(255),
PRIMARY KEY (`call_sid`)
) ENGINE=InnoDB COMMENT='A phone call';
) COMMENT='Least cost routing table';
CREATE TABLE IF NOT EXISTS `api_keys`
(
@@ -143,132 +54,99 @@ CREATE TABLE IF NOT EXISTS `api_keys`
PRIMARY KEY (`api_key_sid`)
) ENGINE=InnoDB COMMENT='An authorization token that is used to access the REST api';
CREATE TABLE IF NOT EXISTS `subscriptions`
(
`id` INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE ,
`subscription_sid` CHAR(36) NOT NULL UNIQUE ,
`registration_sid` CHAR(36) NOT NULL,
`event` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='An active sip subscription';
CREATE TABLE IF NOT EXISTS `voip_carriers`
(
`voip_carrier_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255) 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='An external organization that can provide sip trunking and D';
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`)
);
) ENGINE=InnoDB COMMENT='A Carrier or customer PBX that can send or receive calls';
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),
`workload` INTEGER NOT NULL DEFAULT 1,
`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',
`lcr_route_sid` CHAR(36) NOT NULL,
`voip_carrier_sid` CHAR(36) NOT NULL,
`priority` INTEGER NOT NULL DEFAULT 0,
`priority` INTEGER NOT NULL DEFAULT 0 COMMENT 'lower priority carriers are attempted first',
PRIMARY KEY (`lcr_carrier_set_entry_sid`)
);
) COMMENT='An entry in the LCR routing list';
CREATE TABLE IF NOT EXISTS `sip_gateways`
(
`sip_gateway_sid` CHAR(36),
`ipv4` VARCHAR(32) NOT NULL,
`port` INTEGER NOT NULL DEFAULT 5060,
`inbound` BOOLEAN NOT NULL,
`outbound` BOOLEAN NOT NULL,
`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';
CREATE TABLE IF NOT EXISTS `applications`
(
`application_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255) NOT NULL,
`account_sid` CHAR(36) NOT NULL,
`call_hook_sid` CHAR(36),
`call_status_hook_sid` CHAR(36),
`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_voice` VARCHAR(64) NOT NULL DEFAULT 'en-US-Wavenet-C',
`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 with';
) ENGINE=InnoDB COMMENT='A defined set of behaviors to be applied to phone calls ';
CREATE TABLE IF NOT EXISTS `service_providers`
(
`service_provider_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255) 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='An organization that provides communication services to its ';
) ENGINE=InnoDB COMMENT='A partition of the platform used by one service provider';
CREATE TABLE IF NOT EXISTS `accounts`
(
`account_sid` CHAR(36) NOT NULL UNIQUE ,
`name` VARCHAR(255) NOT NULL,
`sip_realm` VARCHAR(255) UNIQUE ,
`service_provider_sid` CHAR(36) NOT NULL,
`registration_hook_sid` CHAR(36),
`device_calling_hook_sid` CHAR(36),
`error_hook_sid` CHAR(36),
`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_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='A single end-user of the platform';
) 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`);
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`);
CREATE INDEX `conferences_conference_sid_idx` ON `conferences` (`conference_sid`);
CREATE INDEX `conference_participants_conference_participant_sid_idx` ON `conference_participants` (`conference_participant_sid`);
ALTER TABLE `conference_participants` ADD FOREIGN KEY call_sid_idxfk (`call_sid`) REFERENCES `calls` (`call_sid`);
ALTER TABLE `conference_participants` ADD FOREIGN KEY conference_sid_idxfk (`conference_sid`) REFERENCES `conferences` (`conference_sid`);
CREATE INDEX `queues_queue_sid_idx` ON `queues` (`queue_sid`);
CREATE INDEX `registrations_registration_sid_idx` ON `registrations` (`registration_sid`);
CREATE INDEX `queue_members_queue_member_sid_idx` ON `queue_members` (`queue_member_sid`);
ALTER TABLE `queue_members` ADD FOREIGN KEY call_sid_idxfk_1 (`call_sid`) REFERENCES `calls` (`call_sid`);
ALTER TABLE `queue_members` ADD FOREIGN KEY queue_sid_idxfk (`queue_sid`) REFERENCES `queues` (`queue_sid`);
CREATE INDEX `calls_call_sid_idx` ON `calls` (`call_sid`);
ALTER TABLE `calls` ADD FOREIGN KEY parent_call_sid_idxfk (`parent_call_sid`) REFERENCES `calls` (`call_sid`);
ALTER TABLE `calls` ADD FOREIGN KEY application_sid_idxfk_1 (`application_sid`) REFERENCES `applications` (`application_sid`);
CREATE INDEX `calls_phone_number_sid_idx` ON `calls` (`phone_number_sid`);
ALTER TABLE `calls` ADD FOREIGN KEY phone_number_sid_idxfk (`phone_number_sid`) REFERENCES `phone_numbers` (`phone_number_sid`);
ALTER TABLE `calls` ADD FOREIGN KEY inbound_user_sid_idxfk (`inbound_user_sid`) REFERENCES `registrations` (`registration_sid`);
ALTER TABLE `calls` ADD FOREIGN KEY outbound_user_sid_idxfk (`outbound_user_sid`) REFERENCES `registrations` (`registration_sid`);
CREATE INDEX `api_keys_api_key_sid_idx` ON `api_keys` (`api_key_sid`);
CREATE INDEX `api_keys_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`);
@@ -276,19 +154,21 @@ ALTER TABLE `api_keys` ADD FOREIGN KEY account_sid_idxfk_1 (`account_sid`) REFER
CREATE INDEX `api_keys_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`);
ALTER TABLE `subscriptions` ADD FOREIGN KEY registration_sid_idxfk (`registration_sid`) REFERENCES `registrations` (`registration_sid`);
CREATE INDEX `voip_carriers_voip_carrier_sid_idx` ON `voip_carriers` (`voip_carrier_sid`);
CREATE INDEX `voip_carriers_name_idx` ON `voip_carriers` (`name`);
CREATE INDEX `webhooks_webhook_sid_idx` ON `webhooks` (`webhook_sid`);
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 `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`);
ALTER TABLE `phone_numbers` ADD FOREIGN KEY account_sid_idxfk_2 (`account_sid`) REFERENCES `accounts` (`account_sid`);
ALTER TABLE `phone_numbers` ADD FOREIGN KEY account_sid_idxfk_3 (`account_sid`) REFERENCES `accounts` (`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`);
@@ -302,7 +182,7 @@ CREATE UNIQUE INDEX `applications_idx_name` ON `applications` (`account_sid`,`na
CREATE INDEX `applications_application_sid_idx` ON `applications` (`application_sid`);
CREATE INDEX `applications_name_idx` ON `applications` (`name`);
CREATE INDEX `applications_account_sid_idx` ON `applications` (`account_sid`);
ALTER TABLE `applications` ADD FOREIGN KEY account_sid_idxfk_3 (`account_sid`) REFERENCES `accounts` (`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`);
@@ -321,6 +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 error_hook_sid_idxfk (`error_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`);