mirror of
https://github.com/jambonz/sbc-inbound.git
synced 2026-07-04 19:11:47 +00:00
wip: if lookup by realm fails try also source IP
This commit is contained in:
+121
-61
@@ -28,6 +28,16 @@ WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND vc.service_provider_sid IS NOT NULL
|
||||
AND vc.is_active = 1`;
|
||||
|
||||
const sqlSelectAllGatewaysForAccountBySourceAddress =
|
||||
`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
|
||||
FROM sip_gateways sg, voip_carriers vc
|
||||
WHERE sg.voip_carrier_sid = vc.voip_carrier_sid
|
||||
AND sg.ipv4 = ?
|
||||
AND sg.inbound = 1
|
||||
AND vc.account_sid IS NOT NULL
|
||||
AND vc.is_active = 1`;
|
||||
|
||||
const sqlCarriersForAccountBySid =
|
||||
`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
|
||||
@@ -94,82 +104,132 @@ module.exports = (srf, logger) => {
|
||||
const uri = parseUri(req.uri);
|
||||
const isDotDecimal = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(uri.host);
|
||||
|
||||
if (isDotDecimal) {
|
||||
if (process.env.JAMBONES_HOSTING) {
|
||||
if (!process.env.SBC_ACCOUNT_SID) return failure;
|
||||
logger.debug(`wasOriginatedFromCarrier: realm ${uri.host}, source ${req.source_address}`);
|
||||
|
||||
/* look for carrier only within that account */
|
||||
const [r] = await pp.query(sqlCarriersForAccountBySid,
|
||||
[process.env.SBC_ACCOUNT_SID, req.source_address, req.source_port]);
|
||||
if (0 === r.length) return failure;
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: r[0],
|
||||
account_sid: process.env.SBC_ACCOUNT_SID
|
||||
};
|
||||
/* hosted jambonz -- accounts must configure carriers to send to their sip realm */
|
||||
if (isDotDecimal && process.env.JAMBONES_HOSTING) {
|
||||
if (!process.env.SBC_ACCOUNT_SID) {
|
||||
logger.debug(`wasOriginatedFromCarrier: hosted jambonz ${process.env.SBC_ACCOUNT_SID}`);
|
||||
return failure;
|
||||
}
|
||||
else {
|
||||
/* we may have a carrier at the service provider level */
|
||||
const [gw] = await pp.query(sqlSelectAllGatewaysForSP);
|
||||
const matches = gw.filter(gatewayMatchesSourceAddress.bind(null, req.source_address));
|
||||
if (matches.length) {
|
||||
/* we have one or more carriers that match. Now we need to find one with a provisioned phone number */
|
||||
const vc_sids = matches.map((m) => `'${m.voip_carrier_sid}'`).join(',');
|
||||
const did = normalizeDID(req.calledNumber);
|
||||
const sql = `SELECT * FROM phone_numbers WHERE number = ${did} AND voip_carrier_sid IN (${vc_sids})`;
|
||||
logger.debug({matches, sql, did, vc_sids}, 'looking up DID');
|
||||
|
||||
const [r] = await pp.query(sql);
|
||||
if (0 === r.length) {
|
||||
/* came from a carrier, but number is not provisioned..
|
||||
check if we only have a single account, otherwise we have no
|
||||
way of knowing which account this is for
|
||||
*/
|
||||
const [r] = await pp.query('SELECT count(*) as count from accounts where service_provider_sid = ?',
|
||||
matches[0].service_provider_sid);
|
||||
if (r[0].count === 0) return {fromCarrier: true};
|
||||
else {
|
||||
const [accounts] = await pp.query('SELECT * from accounts where service_provider_sid = ?',
|
||||
matches[0].service_provider_sid);
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: matches[0],
|
||||
account_sid: accounts[0].account_sid,
|
||||
account: accounts[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
const gateway = matches.find((m) => m.voip_carrier_sid === r[0].voip_carrier_sid);
|
||||
const [accounts] = await pp.query(sqlAccountBySid, r[0].account_sid);
|
||||
assert(accounts.length);
|
||||
/* exception: dedicated SBC */
|
||||
const [r] = await pp.query(sqlCarriersForAccountBySid,
|
||||
[process.env.SBC_ACCOUNT_SID, req.source_address, req.source_port]);
|
||||
if (0 === r.length) {
|
||||
logger.debug(
|
||||
`wasOriginatedFromCarrier: hosted jambonz (deicated sbc) no carriers for ${process.env.SBC_ACCOUNT_SID}`);
|
||||
return failure;
|
||||
}
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: r[0],
|
||||
account_sid: process.env.SBC_ACCOUNT_SID
|
||||
};
|
||||
}
|
||||
|
||||
if (!isDotDecimal) {
|
||||
/* 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 gw = gwAcc.concat(gwSP);
|
||||
const selected = gw.find(gatewayMatchesSourceAddress.bind(null, req.source_address));
|
||||
if (selected) {
|
||||
const [a] = await pp.query(sqlAccountByRealm, uri.host);
|
||||
if (1 === a.length) {
|
||||
logger.debug({
|
||||
realm: uri.host,
|
||||
source_address: req.source_address,
|
||||
account_sid: a[0].account_sid
|
||||
}, 'wasOriginatedFromCarrier: (true) found carrier and account');
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway,
|
||||
account_sid: r[0].account_sid,
|
||||
application_sid: r[0].application_sid,
|
||||
account: accounts[0]
|
||||
gateway: selected,
|
||||
account_sid: a[0].account_sid,
|
||||
application_sid: selected.application_sid,
|
||||
account: a[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
if (process.env.JAMBONES_HOSTING) {
|
||||
logger.debug('wasOriginatedFromCarrier: unknown realm (hosted jambonz');
|
||||
return failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 gw = gwAcc.concat(gwSP);
|
||||
const selected = gw.find(gatewayMatchesSourceAddress.bind(null, req.source_address));
|
||||
if (selected) {
|
||||
const [a] = await pp.query(sqlAccountByRealm, uri.host);
|
||||
if (0 === a.length) return failure;
|
||||
/* this is a self-hosted system (not a hosted jambonz system)
|
||||
the req.uri is either an IP or a realm we did not find */
|
||||
/* check for a carrier at the service provider level with an inbound gw = source IP */
|
||||
const [gw] = await pp.query(sqlSelectAllGatewaysForSP);
|
||||
const matches = gw.filter(gatewayMatchesSourceAddress.bind(null, req.source_address));
|
||||
if (matches.length) {
|
||||
/* we have one or more carriers that match. Now we need to find one with a provisioned phone number */
|
||||
const vc_sids = matches.map((m) => `'${m.voip_carrier_sid}'`).join(',');
|
||||
const did = normalizeDID(req.calledNumber);
|
||||
const sql = `SELECT * FROM phone_numbers WHERE number = ${did} AND voip_carrier_sid IN (${vc_sids})`;
|
||||
logger.debug({
|
||||
matches, sql, did, vc_sids
|
||||
}, 'wasOriginatedFromCarrier: looking up DID for service provider carrier');
|
||||
|
||||
const [r] = await pp.query(sql);
|
||||
if (0 === r.length) {
|
||||
/* came from a carrier, but number is not provisioned..
|
||||
check if we only have a single account, otherwise we have no
|
||||
way of knowing which account this is for
|
||||
*/
|
||||
const [r] = await pp.query('SELECT count(*) as count from accounts where service_provider_sid = ?',
|
||||
matches[0].service_provider_sid);
|
||||
if (r[0].count !== 1) {
|
||||
logger.debug('wasOriginatedFromCarrier: call from carrier associated with SP, no DID mapping though');
|
||||
return {fromCarrier: true};
|
||||
}
|
||||
else {
|
||||
const [accounts] = await pp.query('SELECT * from accounts where service_provider_sid = ?',
|
||||
matches[0].service_provider_sid);
|
||||
logger.debug('wasOriginatedFromCarrier: call from carrier associated with SP, with DID mapping');
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: matches[0],
|
||||
account_sid: accounts[0].account_sid,
|
||||
account: accounts[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
const gateway = matches.find((m) => m.voip_carrier_sid === r[0].voip_carrier_sid);
|
||||
const [accounts] = await pp.query(sqlAccountBySid, r[0].account_sid);
|
||||
assert(accounts.length);
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: selected,
|
||||
account_sid: a[0].account_sid,
|
||||
application_sid: selected.application_sid,
|
||||
account: a[0]
|
||||
gateway,
|
||||
account_sid: r[0].account_sid,
|
||||
application_sid: r[0].application_sid,
|
||||
account: accounts[0]
|
||||
};
|
||||
}
|
||||
|
||||
/* not a service provider level carrier -- try account-level with inbound gw = source IP */
|
||||
const [gwAccount] = await pp.query(sqlSelectAllGatewaysForAccountBySourceAddress, req.source_address);
|
||||
if (gwAccount.length) {
|
||||
logger.debug({gwAccount}, 'wasOriginatedFromCarrier: call came from account level carrier');
|
||||
const accountSet = new Set();
|
||||
gwAccount.forEach((gw) => accountSet.add(gw.account_sid));
|
||||
if (accountSet.size > 1) {
|
||||
logger.info({accounts: accountSet},
|
||||
`wasOriginatedFromCarrier: ${accountSet.size} accounts found with ${req.source_address} inbound gw`);
|
||||
return failure;
|
||||
}
|
||||
const [accounts] = await pp.query('SELECT * from accounts where account_sid = ?',
|
||||
gwAccount[0].account_sid);
|
||||
logger.debug('wasOriginatedFromCarrier: call from carrier associated with account');
|
||||
return {
|
||||
fromCarrier: true,
|
||||
gateway: gwAccount[0],
|
||||
account_sid: accounts[0].account_sid,
|
||||
account: accounts[0]
|
||||
};
|
||||
}
|
||||
|
||||
logger.info(`wasOriginatedFromCarrier: no carrier found for host: ${req.uri} source: ${req.source_address}`);
|
||||
return failure;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app",
|
||||
"test": "NODE_ENV=test JAMBONES_NETWORK_CIDR='127.0.0.1/32' JAMBONES_HOSTING=1 SBC_ACCOUNT_SID=ed649e33-e771-403a-8c99-1780eabbc803 JAMBONES_TIME_SERIES_HOST=127.0.0.1 JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=error DRACHTIO_SECRET=cymru DRACHTIO_HOST=127.0.0.1 DRACHTIO_PORT=9060 JAMBONES_RTPENGINES=127.0.0.1:12222 JAMBONES_FEATURE_SERVERS=172.38.0.11 node test/ ",
|
||||
"test": "NODE_ENV=test JAMBONES_NETWORK_CIDR='127.0.0.1/32' JAMBONES_HOSTING=1 SBC_ACCOUNT_SID=ed649e33-e771-403a-8c99-1780eabbc803 JAMBONES_TIME_SERIES_HOST=127.0.0.1 JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=localhost JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=debug 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/ ",
|
||||
"coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test",
|
||||
"jslint": "eslint app.js lib"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user