mirror of
https://github.com/jambonz/sbc-inbound.git
synced 2026-10-04 02:04:22 +00:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5ea0740a9 | ||
|
|
79b2a99fe8 | ||
|
|
cd48675499 | ||
|
|
cecdbdccef | ||
|
|
6586919c86 | ||
|
|
c919438af5 | ||
|
|
ab39525467 | ||
|
|
61a66ab181 | ||
|
|
48dd7ebfcd | ||
|
|
678fe9d9a8 | ||
|
|
39bd65fb97 | ||
|
|
3f0fd794ce | ||
|
|
876cb393f9 | ||
|
|
fa2259d6e5 | ||
|
|
2405190dcc | ||
|
|
e9a5921b19 | ||
|
|
6efe714d49 | ||
|
|
4150454736 | ||
|
|
73eb8e8d17 |
@@ -15,7 +15,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: prepare tag
|
||||
id: prepare_tag
|
||||
@@ -37,14 +37,14 @@ jobs:
|
||||
echo "image_id=$IMAGE_ID" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
FROM --platform=linux/amd64 node:20.13.0-alpine3.18 as base
|
||||
FROM --platform=linux/amd64 node:24-alpine AS base
|
||||
|
||||
RUN apk --update --no-cache add --virtual .builds-deps build-base python3
|
||||
|
||||
WORKDIR /opt/app/
|
||||
|
||||
FROM base as build
|
||||
FROM base AS build
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
|
||||
@@ -18,6 +18,6 @@ COPY --from=build /opt/app /opt/app/
|
||||
|
||||
ARG NODE_ENV
|
||||
|
||||
ENV NODE_ENV $NODE_ENV
|
||||
ENV NODE_ENV=$NODE_ENV
|
||||
|
||||
CMD [ "node", "app.js" ]
|
||||
|
||||
@@ -64,12 +64,21 @@ const {
|
||||
password: process.env.JAMBONES_MYSQL_PASSWORD,
|
||||
database: process.env.JAMBONES_MYSQL_DATABASE,
|
||||
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
||||
}, logger);
|
||||
}, logger, process.env.JAMBONES_MYSQL_WRITE_HOST && process.env.JAMBONES_MYSQL_WRITE_USER &&
|
||||
process.env.JAMBONES_MYSQL_WRITE_PASSWORD && process.env.JAMBONES_MYSQL_WRITE_DATABASE ? {
|
||||
host: process.env.JAMBONES_MYSQL_WRITE_HOST,
|
||||
port: process.env.JAMBONES_MYSQL_WRITE_PORT || 3306,
|
||||
user: process.env.JAMBONES_MYSQL_WRITE_USER,
|
||||
password: process.env.JAMBONES_MYSQL_WRITE_PASSWORD,
|
||||
database: process.env.JAMBONES_MYSQL_WRITE_DATABASE,
|
||||
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
||||
} : null);
|
||||
const {
|
||||
client: redisClient,
|
||||
addKey,
|
||||
deleteKey,
|
||||
retrieveKey,
|
||||
retrieveHash,
|
||||
createSet,
|
||||
retrieveSet,
|
||||
addToSet,
|
||||
@@ -117,6 +126,7 @@ srf.locals = {...srf.locals,
|
||||
addKey,
|
||||
deleteKey,
|
||||
retrieveKey,
|
||||
retrieveHash,
|
||||
createSet,
|
||||
incrKey,
|
||||
decrKey,
|
||||
|
||||
+46
-1
@@ -19,6 +19,9 @@ const debug = require('debug')('jambonz:sbc-inbound');
|
||||
const MS_TEAMS_USER_AGENT = 'Microsoft.PSTNHub.SIPProxy';
|
||||
const MS_TEAMS_SIP_ENDPOINT = 'sip.pstnhub.microsoft.com';
|
||||
const IMMUTABLE_HEADERS = ['via', 'from', 'to', 'call-id', 'cseq', 'max-forwards', 'content-length'];
|
||||
const NONCOPYABLE_RESPONSE_HEADERS = [
|
||||
'via', 'from', 'to', 'call-id', 'cseq', 'contact', 'content-length', 'content-type'
|
||||
];
|
||||
|
||||
/**
|
||||
* this is to make sure the outgoing From has the number in the incoming From
|
||||
@@ -66,6 +69,7 @@ class CallSession extends Emitter {
|
||||
this.decrKey = req.srf.locals.realtimeDbHelpers.decrKey;
|
||||
this.addKey = req.srf.locals.realtimeDbHelpers.addKey;
|
||||
this.retrieveKey = req.srf.locals.realtimeDbHelpers.retrieveKey;
|
||||
this.retrieveHash = req.srf.locals.realtimeDbHelpers.retrieveHash;
|
||||
|
||||
this._mediaPath = MediaPath.FullMedia;
|
||||
|
||||
@@ -280,6 +284,7 @@ class CallSession extends Emitter {
|
||||
proxy,
|
||||
headers,
|
||||
responseHeaders,
|
||||
passFailure: false,
|
||||
proxyRequestHeaders: [
|
||||
'all',
|
||||
'-Authorization',
|
||||
@@ -332,6 +337,15 @@ class CallSession extends Emitter {
|
||||
},
|
||||
});
|
||||
|
||||
// passing gateway outbound auth that sbc-inbound can send RE-INVITE with authentication process on UAS side
|
||||
const {gateway} = this.req.locals;
|
||||
if (gateway && gateway.register_username && gateway.register_password) {
|
||||
this.logger.debug('passing outbound gateway auth to CallSession for reinvite processing');
|
||||
uas.auth = {
|
||||
username: gateway.register_username,
|
||||
password: gateway.register_password
|
||||
};
|
||||
}
|
||||
// successfully connected
|
||||
this.logger.info('call connected successfully to feature server');
|
||||
debug('call connected successfully to feature server');
|
||||
@@ -344,6 +358,19 @@ class CallSession extends Emitter {
|
||||
const tags = ['accepted:no', `sipStatus:${err.status}`, `originator:${this.req.locals.originator}`];
|
||||
this.stats.increment('sbc.terminations', tags);
|
||||
this.logger.info(`call failed to connect to feature server with ${err.status}`);
|
||||
|
||||
/* capture trace_id and application_sid from the feature server's error response for the CDR. */
|
||||
if (this.req.locals.cdr && err.res) {
|
||||
const trace_id = err.res.get('X-Trace-ID');
|
||||
if (trace_id) {
|
||||
this.req.locals.cdr.trace_id = trace_id;
|
||||
}
|
||||
const application_sid = err.res.get('X-Application-Sid');
|
||||
if (application_sid) {
|
||||
this.req.locals.cdr.application_sid = application_sid;
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('failed');
|
||||
}
|
||||
else if (err.message !== 'call canceled') {
|
||||
@@ -358,6 +385,22 @@ class CallSession extends Emitter {
|
||||
.catch((err) => this.logger.error(err, 'Error decrementing call counts'));
|
||||
|
||||
}
|
||||
|
||||
/* manually proxy the failure response to UAS so that the trace_id/application_sid capture above runs before
|
||||
res.end fires (which is what triggers the failure-CDR writer). */
|
||||
if (err.message !== 'call canceled' && !this.res.finalResponseSent) {
|
||||
if (err instanceof SipError && err.res) {
|
||||
const headers = {};
|
||||
Object.keys(err.res.headers || {}).forEach((h) => {
|
||||
if (!NONCOPYABLE_RESPONSE_HEADERS.includes(h)) headers[h] = err.res.headers[h];
|
||||
});
|
||||
this.res.send(err.status, err.reason, {headers});
|
||||
}
|
||||
else {
|
||||
this.res.send(err.status || 500, err.reason);
|
||||
}
|
||||
}
|
||||
|
||||
this.srf.endSession(this.req);
|
||||
}
|
||||
}
|
||||
@@ -482,7 +525,9 @@ class CallSession extends Emitter {
|
||||
this.req.locals.carrier :
|
||||
this.req.locals.originator;
|
||||
const application = await this.srf.locals.getApplicationBySid(application_sid);
|
||||
const isRecording = this.req.locals.account.record_all_calls || (application && application.record_all_calls);
|
||||
const {hasRecording} = await this.retrieveHash(`call:${this.account_sid}:${call_sid}`) ?? {};
|
||||
const isRecording = this.req.locals.account.record_all_calls ||
|
||||
(application && application.record_all_calls) || hasRecording;
|
||||
const day = new Date();
|
||||
let recording_url = `/Accounts/${this.account_sid}/RecentCalls/${call_sid}/record`;
|
||||
recording_url += `/${day.getFullYear()}/${(day.getMonth() + 1).toString().padStart(2, '0')}`;
|
||||
|
||||
+68
-22
@@ -7,7 +7,8 @@ const sqlSelectSPForAccount = 'SELECT service_provider_sid FROM accounts WHERE a
|
||||
|
||||
const sqlSelectAllCarriersForAccountByRealm =
|
||||
`SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.account_sid,
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc, accounts acc
|
||||
WHERE acc.sip_realm = ?
|
||||
AND vc.account_sid = acc.account_sid
|
||||
@@ -17,7 +18,8 @@ AND sg.voip_carrier_sid = vc.voip_carrier_sid`;
|
||||
|
||||
const sqlSelectAllCarriersForSPByRealm =
|
||||
`SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.account_sid,
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc, accounts acc
|
||||
WHERE acc.sip_realm = ?
|
||||
AND vc.service_provider_sid = acc.service_provider_sid
|
||||
@@ -26,14 +28,30 @@ AND vc.is_active = 1
|
||||
AND sg.inbound = 1
|
||||
AND sg.voip_carrier_sid = vc.voip_carrier_sid`;
|
||||
|
||||
const sqlSelectAllGatewaysForSP =
|
||||
`SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.service_provider_sid,
|
||||
vc.account_sid, vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto
|
||||
const sqlSelectExactGatewayForSP =
|
||||
`SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.service_provider_sid,
|
||||
vc.account_sid, vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc
|
||||
WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND vc.service_provider_sid IS NOT NULL
|
||||
AND vc.is_active = 1
|
||||
AND sg.inbound = 1`;
|
||||
WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND vc.service_provider_sid IS NOT NULL
|
||||
AND vc.is_active = 1
|
||||
AND sg.inbound = 1
|
||||
AND sg.netmask = 32
|
||||
AND sg.ipv4 = ?
|
||||
ORDER BY vc.account_sid IS NOT NULL DESC`;
|
||||
|
||||
const sqlSelectCIDRGatewaysForSP =
|
||||
`SELECT STRAIGHT_JOIN sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.service_provider_sid,
|
||||
vc.account_sid, vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc
|
||||
WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND vc.service_provider_sid IS NOT NULL
|
||||
AND vc.is_active = 1
|
||||
AND sg.inbound = 1
|
||||
AND sg.netmask < 32
|
||||
ORDER BY sg.netmask DESC`;
|
||||
|
||||
const sqlAccountByRealm = 'SELECT * from accounts WHERE sip_realm = ? AND is_active = 1';
|
||||
const sqlAccountBySid = 'SELECT * from accounts WHERE account_sid = ?';
|
||||
@@ -57,7 +75,8 @@ AND outbound = 1`;
|
||||
|
||||
const sqlSelectCarrierRequiringRegistration = `
|
||||
SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.service_provider_sid, vc.account_sid,
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto
|
||||
vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc
|
||||
WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND vc.requires_register = 1
|
||||
@@ -77,7 +96,8 @@ AND (
|
||||
|
||||
const sqlSelectGatewaysByVoipCarrierSids = `
|
||||
SELECT sg.sip_gateway_sid, sg.voip_carrier_sid, vc.name, vc.service_provider_sid,
|
||||
vc.account_sid, vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto
|
||||
vc.account_sid, vc.application_sid, sg.inbound, sg.outbound, sg.is_active, sg.ipv4, sg.netmask, sg.pad_crypto,
|
||||
vc.register_username, vc.register_password
|
||||
FROM sip_gateways sg, voip_carriers vc
|
||||
WHERE sg.voip_carrier_sid IN (?)
|
||||
AND sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
@@ -294,7 +314,7 @@ module.exports = (srf, logger) => {
|
||||
|
||||
/* get all the carriers and gateways for the account owning this sip realm */
|
||||
const [gwAcc] = await pp.query(sqlSelectAllCarriersForAccountByRealm, [uri.host]);
|
||||
const [gwSP] = gwAcc.length ? [[]] : await pp.query(sqlSelectAllCarriersForSPByRealm, uri.host);
|
||||
const [gwSP] = await pp.query(sqlSelectAllCarriersForSPByRealm, uri.host);
|
||||
const gw = gwAcc
|
||||
.concat(gwSP)
|
||||
.sort((a, b) => b.netmask - a.netmask);
|
||||
@@ -305,7 +325,9 @@ module.exports = (srf, logger) => {
|
||||
name: gw.name,
|
||||
service_provider_sid: gw.service_provider_sid,
|
||||
account_sid: gw.account_sid,
|
||||
application_sid: gw.application_sid
|
||||
application_sid: gw.application_sid,
|
||||
register_username: gw.register_username,
|
||||
register_password: gw.register_password
|
||||
};
|
||||
});
|
||||
/* remove duplicates, winnow down to voip_carriers, not gateways */
|
||||
@@ -326,7 +348,8 @@ module.exports = (srf, logger) => {
|
||||
service_provider_sid: gw.service_provider_sid,
|
||||
account_sid: gw.account_sid,
|
||||
application_sid: gw.application_sid,
|
||||
pad_crypto: gw.pad_crypto
|
||||
register_username: gw.register_username,
|
||||
register_password: gw.register_password
|
||||
};
|
||||
});
|
||||
/* remove duplicates */
|
||||
@@ -371,8 +394,13 @@ module.exports = (srf, logger) => {
|
||||
}
|
||||
}
|
||||
if (r.length > 1) {
|
||||
logger.info({r},
|
||||
'multiple carriers with the same gateway have the same number provisioned for the same account'
|
||||
const all = r.map(({account_sid, voip_carrier_sid}) => ({account_sid, voip_carrier_sid}));
|
||||
logger.info({
|
||||
number: r[0].number,
|
||||
total: all.length,
|
||||
matches: all.slice(0, 5)
|
||||
},
|
||||
'multiple carriers with the same gateway have the same number provisioned for the same account'
|
||||
+ ' -- cannot determine which one to use');
|
||||
return {
|
||||
fromCarrier: true,
|
||||
@@ -447,10 +475,19 @@ module.exports = (srf, logger) => {
|
||||
}
|
||||
|
||||
/* find all carrier entries that have an inbound gateway matching the source IP */
|
||||
const [gw] = await pp.query(sqlSelectAllGatewaysForSP);
|
||||
/* Query both exact IP matches AND CIDR ranges in parallel to handle the case where
|
||||
multiple accounts have configured the same carrier with different netmasks.
|
||||
The phone number lookup will disambiguate which account owns the call. */
|
||||
const [[gwExact], [gwCidr]] = await Promise.all([
|
||||
pp.query(sqlSelectExactGatewayForSP, [req.source_address]),
|
||||
pp.query(sqlSelectCIDRGatewaysForSP)
|
||||
]);
|
||||
|
||||
/* Merge both result sets - exact matches first, then CIDR ranges (already sorted by netmask DESC) */
|
||||
const gw = [...gwExact, ...gwCidr];
|
||||
|
||||
//logger.debug({gw}, `checking gateways for source address ${req.source_address}`);
|
||||
let matches = gw
|
||||
.sort((a, b) => b.netmask - a.netmask)
|
||||
.filter(gatewayMatchesSourceAddress.bind(null, logger, req.source_address))
|
||||
.map((gw) => {
|
||||
return {
|
||||
@@ -459,7 +496,9 @@ module.exports = (srf, logger) => {
|
||||
service_provider_sid: gw.service_provider_sid,
|
||||
account_sid: gw.account_sid,
|
||||
application_sid: gw.application_sid,
|
||||
pad_crypto: gw.pad_crypto
|
||||
pad_crypto: gw.pad_crypto,
|
||||
register_username: gw.register_username,
|
||||
register_password: gw.register_password
|
||||
};
|
||||
});
|
||||
/* remove duplicates, winnow down to voip_carriers, not gateways */
|
||||
@@ -479,7 +518,9 @@ module.exports = (srf, logger) => {
|
||||
service_provider_sid: gw.service_provider_sid,
|
||||
account_sid: gw.account_sid,
|
||||
application_sid: gw.application_sid,
|
||||
pad_crypto: gw.pad_crypto
|
||||
pad_crypto: gw.pad_crypto,
|
||||
register_username: gw.register_username,
|
||||
register_password: gw.register_password
|
||||
};
|
||||
});
|
||||
/* remove duplicates */
|
||||
@@ -565,8 +606,13 @@ module.exports = (srf, logger) => {
|
||||
}
|
||||
}
|
||||
else if (r.length > 1) {
|
||||
logger.info({r},
|
||||
'multiple accounts have added this carrier with default routing -- cannot determine which to use');
|
||||
const all = r.map(({account_sid, voip_carrier_sid}) => ({account_sid, voip_carrier_sid}));
|
||||
logger.info({
|
||||
number: r[0].number,
|
||||
total: all.length,
|
||||
matches: all.slice(0, 5)
|
||||
},
|
||||
'multiple accounts have added this carrier with default routing -- cannot determine which to use');
|
||||
return {
|
||||
fromCarrier: true,
|
||||
error: 'Multiple accounts are attempting to route the same phone number from the same carrier'
|
||||
|
||||
+6
-4
@@ -59,13 +59,15 @@ module.exports = function(srf, logger) {
|
||||
|
||||
/* write cdr for non-success response here */
|
||||
res.once('end', ({status}) => {
|
||||
if (req.locals.cdr && req.locals.cdr.account_sid && status > 200 && 401 !== status) {
|
||||
const trunk = ['trunk', 'teams'].includes(req.locals.originator) ? req.locals.carrier : req.locals.originator;
|
||||
if (req.locals.cdr && req.locals.cdr.account_sid && status > 200 && 401 !== status) {
|
||||
const trunk = ['trunk', 'teams'].includes(req.locals.originator) ?
|
||||
req.locals.carrier : req.locals.originator;
|
||||
writeCdrs({...req.locals.cdr,
|
||||
terminated_at: Date.now(),
|
||||
termination_reason: status === 487 === status ? 'caller abandoned' : 'failed',
|
||||
termination_reason: status === 487 ? 'caller abandoned' : 'failed',
|
||||
sip_status: status,
|
||||
trunk
|
||||
trunk,
|
||||
...(req.locals.application_sid && {application_sid: req.locals.application_sid})
|
||||
}).catch((err) => logger.error({err}, 'Error writing cdr for call failure'));
|
||||
}
|
||||
});
|
||||
|
||||
Generated
+1173
-851
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "sbc-inbound",
|
||||
"version": "0.9.5",
|
||||
"version": "0.9.6",
|
||||
"main": "app.js",
|
||||
"engines": {
|
||||
"node": ">= 18.0.0"
|
||||
"node": ">= 20.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"sip",
|
||||
@@ -30,7 +30,7 @@
|
||||
"@aws-sdk/client-sns": "^3.549.0",
|
||||
"@babel/helpers": "^7.26.10",
|
||||
"@jambonz/db-helpers": "^0.9.18",
|
||||
"@jambonz/digest-utils": "^0.0.8",
|
||||
"@jambonz/digest-utils": "^0.0.9",
|
||||
"@jambonz/http-health-check": "^0.0.1",
|
||||
"@jambonz/realtimedb-helpers": "^0.8.18",
|
||||
"@jambonz/rtpengine-utils": "^0.4.4",
|
||||
@@ -39,10 +39,10 @@
|
||||
"@jambonz/time-series": "^0.2.10",
|
||||
"bent": "^7.3.12",
|
||||
"cidr-matcher": "^2.1.1",
|
||||
"debug": "^4.3.4",
|
||||
"debug": "^4.4.3",
|
||||
"drachtio-fn-b2b-sugar": "0.2.1",
|
||||
"drachtio-srf": "^5.0.5",
|
||||
"express": "^4.19.2",
|
||||
"drachtio-srf": "^5.0.21",
|
||||
"express": "^4.21.2",
|
||||
"pino": "^10.1.0",
|
||||
"verify-aws-sns-signature": "^0.1.0",
|
||||
"xml2js": "^0.6.2"
|
||||
|
||||
+28
-24
@@ -14,6 +14,8 @@ DROP TABLE IF EXISTS beta_invite_codes;
|
||||
|
||||
DROP TABLE IF EXISTS call_routes;
|
||||
|
||||
DROP TABLE IF EXISTS clients;
|
||||
|
||||
DROP TABLE IF EXISTS dns_records;
|
||||
|
||||
DROP TABLE IF EXISTS lcr;
|
||||
@@ -66,8 +68,6 @@ DROP TABLE IF EXISTS phone_numbers;
|
||||
|
||||
DROP TABLE IF EXISTS sip_gateways;
|
||||
|
||||
DROP TABLE IF EXISTS clients;
|
||||
|
||||
DROP TABLE IF EXISTS voip_carriers;
|
||||
|
||||
DROP TABLE IF EXISTS accounts;
|
||||
@@ -132,6 +132,19 @@ application_sid CHAR(36) NOT NULL,
|
||||
PRIMARY KEY (call_route_sid)
|
||||
) COMMENT='a regex-based pattern match for call routing';
|
||||
|
||||
CREATE TABLE clients
|
||||
(
|
||||
client_sid CHAR(36) NOT NULL UNIQUE ,
|
||||
account_sid CHAR(36) NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT 1,
|
||||
username VARCHAR(64),
|
||||
password VARCHAR(1024),
|
||||
allow_direct_app_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
allow_direct_queue_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
allow_direct_user_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (client_sid)
|
||||
);
|
||||
|
||||
CREATE TABLE dns_records
|
||||
(
|
||||
dns_record_sid CHAR(36) NOT NULL UNIQUE ,
|
||||
@@ -191,6 +204,7 @@ tech_prefix VARCHAR(16) COMMENT 'tech prefix to prepend to outbound calls to thi
|
||||
inbound_auth_username VARCHAR(64),
|
||||
inbound_auth_password VARCHAR(64),
|
||||
diversion VARCHAR(32),
|
||||
trunk_type ENUM('static_ip','auth','reg') NOT NULL DEFAULT 'static_ip',
|
||||
PRIMARY KEY (predefined_carrier_sid)
|
||||
);
|
||||
|
||||
@@ -405,7 +419,7 @@ register_public_ip_in_contact BOOLEAN NOT NULL DEFAULT false,
|
||||
register_status VARCHAR(4096),
|
||||
dtmf_type ENUM('rfc2833','tones','info') NOT NULL DEFAULT 'rfc2833',
|
||||
outbound_sip_proxy VARCHAR(255),
|
||||
trunk_type ENUM('static-ip','auth','registration') NOT NULL DEFAULT 'static-ip',
|
||||
trunk_type ENUM('static_ip','auth','reg') NOT NULL DEFAULT 'static_ip',
|
||||
PRIMARY KEY (voip_carrier_sid)
|
||||
) COMMENT='A Carrier or customer PBX that can send or receive calls';
|
||||
|
||||
@@ -479,20 +493,6 @@ password VARCHAR(255),
|
||||
PRIMARY KEY (webhook_sid)
|
||||
) COMMENT='An HTTP callback';
|
||||
|
||||
CREATE TABLE clients
|
||||
(
|
||||
client_sid CHAR(36) NOT NULL UNIQUE ,
|
||||
account_sid CHAR(36) NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT 1,
|
||||
username VARCHAR(64),
|
||||
password VARCHAR(1024),
|
||||
allow_direct_app_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
allow_direct_queue_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
allow_direct_user_calling BOOLEAN NOT NULL DEFAULT 1,
|
||||
voip_carrier_sid CHAR(36),
|
||||
PRIMARY KEY (client_sid)
|
||||
);
|
||||
|
||||
CREATE TABLE applications
|
||||
(
|
||||
application_sid CHAR(36) NOT NULL UNIQUE ,
|
||||
@@ -505,7 +505,7 @@ messaging_hook_sid CHAR(36) COMMENT 'webhook to call for inbound SMS/MMS ',
|
||||
app_json TEXT,
|
||||
speech_synthesis_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||
speech_synthesis_language VARCHAR(12) NOT NULL DEFAULT 'en-US',
|
||||
speech_synthesis_voice VARCHAR(256),
|
||||
speech_synthesis_voice VARCHAR(256) DEFAULT 'en-US-Standard-C',
|
||||
speech_synthesis_label VARCHAR(64),
|
||||
speech_recognizer_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||
speech_recognizer_language VARCHAR(64) NOT NULL DEFAULT 'en-US',
|
||||
@@ -582,6 +582,9 @@ ALTER TABLE call_routes ADD FOREIGN KEY account_sid_idxfk_3 (account_sid) REFERE
|
||||
|
||||
ALTER TABLE call_routes ADD FOREIGN KEY application_sid_idxfk (application_sid) REFERENCES applications (application_sid);
|
||||
|
||||
CREATE INDEX client_sid_idx ON clients (client_sid);
|
||||
ALTER TABLE clients ADD CONSTRAINT account_sid_idxfk_13 FOREIGN KEY account_sid_idxfk_13 (account_sid) REFERENCES accounts (account_sid);
|
||||
|
||||
CREATE INDEX dns_record_sid_idx ON dns_records (dns_record_sid);
|
||||
ALTER TABLE dns_records ADD FOREIGN KEY account_sid_idxfk_4 (account_sid) REFERENCES accounts (account_sid);
|
||||
|
||||
@@ -702,6 +705,12 @@ ALTER TABLE phone_numbers ADD FOREIGN KEY service_provider_sid_idxfk_8 (service_
|
||||
|
||||
CREATE INDEX sip_gateway_idx_hostport ON sip_gateways (ipv4,port);
|
||||
|
||||
CREATE INDEX idx_sip_gateways_inbound_carrier ON sip_gateways (inbound,voip_carrier_sid);
|
||||
|
||||
CREATE INDEX idx_sip_gateways_inbound_lookup ON sip_gateways (inbound,netmask,ipv4);
|
||||
|
||||
CREATE INDEX idx_sip_gateways_inbound_netmask ON sip_gateways (inbound,netmask);
|
||||
|
||||
CREATE INDEX voip_carrier_sid_idx ON sip_gateways (voip_carrier_sid);
|
||||
ALTER TABLE sip_gateways ADD FOREIGN KEY voip_carrier_sid_idxfk_2 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||
|
||||
@@ -710,11 +719,6 @@ ALTER TABLE lcr_carrier_set_entry ADD FOREIGN KEY lcr_route_sid_idxfk (lcr_route
|
||||
ALTER TABLE lcr_carrier_set_entry ADD FOREIGN KEY voip_carrier_sid_idxfk_3 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||
|
||||
CREATE INDEX webhook_sid_idx ON webhooks (webhook_sid);
|
||||
CREATE INDEX client_sid_idx ON clients (client_sid);
|
||||
ALTER TABLE clients ADD CONSTRAINT account_sid_idxfk_13 FOREIGN KEY account_sid_idxfk_13 (account_sid) REFERENCES accounts (account_sid);
|
||||
|
||||
ALTER TABLE clients ADD FOREIGN KEY voip_carrier_sid_idxfk_4 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
|
||||
|
||||
CREATE UNIQUE INDEX applications_idx_name ON applications (account_sid,name);
|
||||
|
||||
CREATE INDEX application_sid_idx ON applications (application_sid);
|
||||
@@ -748,4 +752,4 @@ ALTER TABLE accounts ADD FOREIGN KEY device_calling_application_sid_idxfk (devic
|
||||
|
||||
ALTER TABLE accounts ADD FOREIGN KEY siprec_hook_sid_idxfk (siprec_hook_sid) REFERENCES applications (application_sid);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
@@ -129,7 +129,7 @@ values ('acct-100', 'Account 100', '3f35518f-5a0d-4c2e-90a5-2407bb3b36f0', 'foob
|
||||
insert into voip_carriers (voip_carrier_sid, name, account_sid, service_provider_sid, trunk_type,
|
||||
requires_register, register_username, register_sip_realm, register_password, is_active)
|
||||
values ('4a7d1c8e-5f2b-4d9a-8e3c-6b5a9f1e4c7d', 'test-registration-trunk', 'ed649e33-e771-403a-8c99-1780eabbc803',
|
||||
'3f35518f-5a0d-4c2e-90a5-2407bb3b36f0', 'registration', true, 'testuser',
|
||||
'3f35518f-5a0d-4c2e-90a5-2407bb3b36f0', 'reg', true, 'testuser',
|
||||
'sip.carrier.example.com', 'testpass', true);
|
||||
|
||||
-- sip_gateway for outbound only (inbound will use ephemeral gateway from Redis)
|
||||
|
||||
Reference in New Issue
Block a user