mirror of
https://github.com/jambonz/sbc-outbound.git
synced 2026-01-25 02:07:59 +00:00
check if sip gateway is in blacklist before sending outbound call (#119)
* check if sip gateway is in blacklist before sending outbound call * wip * wip * wip * add testcase for blacklist * wip
This commit is contained in:
1
app.js
1
app.js
@@ -97,6 +97,7 @@ srf.locals = {...srf.locals,
|
|||||||
lookupCarrierByAccountLcr
|
lookupCarrierByAccountLcr
|
||||||
},
|
},
|
||||||
realtimeDbHelpers: {
|
realtimeDbHelpers: {
|
||||||
|
client: redisClient,
|
||||||
createHash,
|
createHash,
|
||||||
retrieveHash,
|
retrieveHash,
|
||||||
incrKey,
|
incrKey,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const Emitter = require('events');
|
const Emitter = require('events');
|
||||||
const sdpTransform = require('sdp-transform');
|
const sdpTransform = require('sdp-transform');
|
||||||
const SrsClient = require('@jambonz/siprec-client-utils');
|
const SrsClient = require('@jambonz/siprec-client-utils');
|
||||||
const {makeRtpEngineOpts, nudgeCallCounts, isPrivateVoipNetwork} = require('./utils');
|
const {makeRtpEngineOpts, nudgeCallCounts, isPrivateVoipNetwork, isBlackListedSipGateway} = require('./utils');
|
||||||
const {forwardInDialogRequests} = require('drachtio-fn-b2b-sugar');
|
const {forwardInDialogRequests} = require('drachtio-fn-b2b-sugar');
|
||||||
const {SipError, stringifyUri, parseUri} = require('drachtio-srf');
|
const {SipError, stringifyUri, parseUri} = require('drachtio-srf');
|
||||||
const debug = require('debug')('jambonz:sbc-outbound');
|
const debug = require('debug')('jambonz:sbc-outbound');
|
||||||
@@ -168,7 +168,7 @@ class CallSession extends Emitter {
|
|||||||
subscribeAnswer,
|
subscribeAnswer,
|
||||||
unsubscribe
|
unsubscribe
|
||||||
} = engine;
|
} = engine;
|
||||||
const {createHash, retrieveHash} = this.srf.locals.realtimeDbHelpers;
|
const {client, createHash, retrieveHash} = this.srf.locals.realtimeDbHelpers;
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
this.answer = answer;
|
this.answer = answer;
|
||||||
this.del = del;
|
this.del = del;
|
||||||
@@ -186,7 +186,7 @@ class CallSession extends Emitter {
|
|||||||
|
|
||||||
this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, this.useWss || teams, false, teams);
|
this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, this.useWss || teams, false, 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 = [];
|
||||||
const mapGateways = new Map();
|
const mapGateways = new Map();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -280,7 +280,13 @@ class CallSession extends Emitter {
|
|||||||
}
|
}
|
||||||
const vc = await this.lookupCarrierBySid(voip_carrier_sid);
|
const vc = await this.lookupCarrierBySid(voip_carrier_sid);
|
||||||
const gateways = await this.lookupSipGatewaysByCarrier(voip_carrier_sid);
|
const gateways = await this.lookupSipGatewaysByCarrier(voip_carrier_sid);
|
||||||
const gws = (gateways || [])
|
const goodGateways = [];
|
||||||
|
for (const g of gateways) {
|
||||||
|
if (!await isBlackListedSipGateway(client, this.logger, g.sip_gateway_sid)) {
|
||||||
|
goodGateways.push(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const gws = (goodGateways || [])
|
||||||
.filter((gw) => gw.outbound);
|
.filter((gw) => gw.outbound);
|
||||||
if (gws.length) {
|
if (gws.length) {
|
||||||
uris = [];
|
uris = [];
|
||||||
@@ -332,6 +338,7 @@ class CallSession extends Emitter {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.logger.info({voip_carrier_sid}, 'no outbound gateways found for requested carrier');
|
this.logger.info({voip_carrier_sid}, 'no outbound gateways found for requested carrier');
|
||||||
|
this.res.send(603);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debug(err);
|
debug(err);
|
||||||
|
|||||||
15
lib/utils.js
15
lib/utils.js
@@ -213,6 +213,18 @@ const isPrivateVoipNetwork = async(uri) => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function makeBlacklistGatewayKey(key) {
|
||||||
|
return `blacklist-sip-gateway:${key}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function isBlackListedSipGateway(client, logger, sip_gateway_sid) {
|
||||||
|
try {
|
||||||
|
return await client.exists(makeBlacklistGatewayKey(sip_gateway_sid)) === 1;
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({err}, `isBlackListedSipGateway: error while checking blacklist for ${sip_gateway_sid}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
makeRtpEngineOpts,
|
makeRtpEngineOpts,
|
||||||
selectHostPort,
|
selectHostPort,
|
||||||
@@ -223,5 +235,6 @@ module.exports = {
|
|||||||
systemHealth,
|
systemHealth,
|
||||||
createHealthCheckApp,
|
createHealthCheckApp,
|
||||||
nudgeCallCounts,
|
nudgeCallCounts,
|
||||||
isPrivateVoipNetwork
|
isPrivateVoipNetwork,
|
||||||
|
isBlackListedSipGateway
|
||||||
};
|
};
|
||||||
|
|||||||
59
test/scenarios/uac-pcap-carrier-fail-blacklist.xml
Normal file
59
test/scenarios/uac-pcap-carrier-fail-blacklist.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<scenario name="UAC with media">
|
||||||
|
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
INVITE sip:16173333456@127.0.0.1 SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]
|
||||||
|
To: <sip:16173333456@127.0.0.1>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 INVITE
|
||||||
|
Contact: sip:sipp@[local_ip]:[local_port]
|
||||||
|
Max-Forwards: 70
|
||||||
|
X-Account-Sid: ed649e33-e771-403a-8c99-1780eabbc803
|
||||||
|
X-Call-Sid: ff49e33-e771-403a-8c99-1780eabbc803
|
||||||
|
X-Jambonz-Routing: phone
|
||||||
|
Subject: uac-pcap-carrier-fail-limits
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: [len]
|
||||||
|
|
||||||
|
v=0
|
||||||
|
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
|
||||||
|
s=-
|
||||||
|
c=IN IP[local_ip_type] [local_ip]
|
||||||
|
t=0 0
|
||||||
|
m=audio [auto_media_port] RTP/AVP 8 101
|
||||||
|
a=rtpmap:8 PCMA/8000
|
||||||
|
a=rtpmap:101 telephone-event/8000
|
||||||
|
a=fmtp:101 0-11,16
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="603" rtd="true" crlf="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
ACK sip:sip:+16173333456@127.0.0.1 SIP/2.0
|
||||||
|
[last_Via]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]
|
||||||
|
To: <sip:sip:+16173333456@127.0.0.1>[peer_tag_param]
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 ACK
|
||||||
|
Subject: uac-pcap-carrier-fail-blacklist
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -26,6 +26,7 @@ function connect(connectable) {
|
|||||||
test('sbc-outbound tests', async(t) => {
|
test('sbc-outbound tests', async(t) => {
|
||||||
const {srf} = require('../app');
|
const {srf} = require('../app');
|
||||||
const { queryCdrs } = srf.locals;
|
const { queryCdrs } = srf.locals;
|
||||||
|
const redisClient = srf.locals.realtimeDbHelpers.client;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await connect(srf);
|
await connect(srf);
|
||||||
@@ -95,7 +96,17 @@ test('sbc-outbound tests', async(t) => {
|
|||||||
/* fails when session limit exceeded */
|
/* fails when session limit exceeded */
|
||||||
await sippUac('uac-pcap-carrier-fail-limits.xml');
|
await sippUac('uac-pcap-carrier-fail-limits.xml');
|
||||||
t.pass('fails when max calls in progress');
|
t.pass('fails when max calls in progress');
|
||||||
|
|
||||||
|
// re-rack test data
|
||||||
|
execSync(`mysql -h 127.0.0.1 -u root --protocol=tcp -D jambones_test < ${__dirname}/db/jambones-sql.sql`);
|
||||||
|
execSync(`mysql -h 127.0.0.1 -u root --protocol=tcp -D jambones_test < ${__dirname}/db/populate-test-data.sql`);
|
||||||
|
|
||||||
|
// Black list good carrier for some seconds
|
||||||
|
await redisClient.setex('blacklist-sip-gateway:124a5339-c62c-4075-9e19-f4de70a96597', 3, '');
|
||||||
|
await sippUac('uac-pcap-carrier-fail-blacklist.xml');
|
||||||
|
t.pass('fails when carrier is blacklisted');
|
||||||
|
await redisClient.del('blacklist-sip-gateway:124a5339-c62c-4075-9e19-f4de70a96597');
|
||||||
|
|
||||||
await waitFor(25);
|
await waitFor(25);
|
||||||
|
|
||||||
const res = await queryCdrs({account_sid: 'ed649e33-e771-403a-8c99-1780eabbc803'});
|
const res = await queryCdrs({account_sid: 'ed649e33-e771-403a-8c99-1780eabbc803'});
|
||||||
|
|||||||
Reference in New Issue
Block a user