mirror of
https://github.com/jambonz/sbc-sip-sidecar.git
synced 2026-01-24 22:27:52 +00:00
add support for registration trunks which result in a set of ephemera… (#112)
* add support for registration trunks which result in a set of ephemeral sip gateways to be stored in redis * wip * refactor createEphemeralGateways into realtime dbhelpers * minor * update eslint
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
const dns = require('dns').promises;
|
||||
const {
|
||||
JAMBONES_REGBOT_DEFAULT_EXPIRES_INTERVAL,
|
||||
JAMBONES_REGBOT_MIN_EXPIRES_INTERVAL,
|
||||
@@ -17,24 +18,20 @@ class Regbot {
|
||||
this.logger = logger;
|
||||
|
||||
[
|
||||
'voip_carrier_sid',
|
||||
'ipv4',
|
||||
'port',
|
||||
'username',
|
||||
'password',
|
||||
'sip_realm',
|
||||
'protocol',
|
||||
'account_sip_realm'
|
||||
'account_sip_realm',
|
||||
'outbound_sip_proxy',
|
||||
'trunk_type'
|
||||
].forEach((prop) => this[prop] = opts[prop]);
|
||||
|
||||
this.voip_carrier_sid = opts.voip_carrier_sid;
|
||||
this.username = opts.username;
|
||||
this.password = opts.password;
|
||||
this.sip_realm = opts.sip_realm || opts.ipv4;
|
||||
this.ipv4 = opts.ipv4;
|
||||
this.port = opts.port;
|
||||
this.use_public_ip_in_contact = opts.use_public_ip_in_contact || JAMBONES_REGBOT_CONTACT_USE_IP;
|
||||
this.use_sips_scheme = opts.use_sips_scheme || false;
|
||||
this.outbound_sip_proxy = opts.outbound_sip_proxy;
|
||||
|
||||
this.fromUser = opts.from_user || this.username;
|
||||
const fromDomain = opts.from_domain || this.sip_realm;
|
||||
@@ -72,6 +69,7 @@ class Regbot {
|
||||
}
|
||||
|
||||
async register(srf) {
|
||||
const { createEphemeralGateway } = srf.locals.realtimeDbHelpers;
|
||||
const { updateVoipCarriersRegisterStatus } = srf.locals.dbHelpers;
|
||||
const { writeAlerts, localSIPDomain } = srf.locals;
|
||||
try {
|
||||
@@ -183,6 +181,8 @@ class Regbot {
|
||||
this.timer = setTimeout(this.register.bind(this, srf), (expires / 2) * 1000);
|
||||
}
|
||||
const timestamp = new Date().toISOString();
|
||||
|
||||
//update registration status for the carrier in the database
|
||||
updateVoipCarriersRegisterStatus(this.voip_carrier_sid, JSON.stringify({
|
||||
status: res.status === 200 ? 'ok' : 'fail',
|
||||
reason: `${res.status} ${res.reason}`,
|
||||
@@ -191,6 +191,31 @@ class Regbot {
|
||||
timestamp: timestamp,
|
||||
expires: expires
|
||||
}));
|
||||
|
||||
// for reg trunks, create ephemeral set of IP addresses for inbound gateways
|
||||
if (this.trunk_type === 'reg') {
|
||||
const addresses = [];
|
||||
if (this.port) {
|
||||
const addrs = await dnsResolverA(this.logger, this.sip_realm);
|
||||
addresses.push(...addrs);
|
||||
}
|
||||
else {
|
||||
const addrs = await dnsResolverSrv(this.logger, this.sip_realm, this.transport);
|
||||
addresses.push(...addrs);
|
||||
}
|
||||
|
||||
if (addresses.length) {
|
||||
try {
|
||||
await Promise.all(
|
||||
addresses.map((ip) => createEphemeralGateway(ip, this.voip_carrier_sid, expires))
|
||||
);
|
||||
} catch (err) {
|
||||
this.logger.error({addresses, err}, 'Error creating hash for reg-gateway');
|
||||
}
|
||||
this.logger.debug({addresses},
|
||||
`Created ephemeral gateways for registration trunk ${this.voip_carrier_sid}, ${this.sip_realm}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
this.logger.error({ err }, `${this.aor}: Error registering to ${this.ipv4}:${this.port}`);
|
||||
@@ -204,5 +229,44 @@ class Regbot {
|
||||
}
|
||||
}
|
||||
|
||||
const dnsResolverA = async(logger, hostname) => {
|
||||
try {
|
||||
const addresses = await dns.resolve4(hostname);
|
||||
logger.debug({addresses}, `Regbot: resolved ${hostname} into ${addresses.length} IPs`);
|
||||
return addresses;
|
||||
} catch (err) {
|
||||
logger.info({err}, `Error resolving ${hostname}`);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const dnsResolverSrv = async(logger, hostname, transport) => {
|
||||
let name;
|
||||
switch (transport) {
|
||||
case 'tls':
|
||||
name = `_sips._tcp.${hostname}`;
|
||||
break;
|
||||
case 'tcp':
|
||||
name = `_sip._tcp.${hostname}`;
|
||||
break;
|
||||
default:
|
||||
name = `_sip._udp.${hostname}`;
|
||||
}
|
||||
|
||||
try {
|
||||
const arr = await dns.resolveSrv(name);
|
||||
logger.debug({arr}, `Regbot: resolved ${hostname}/${transport} into ${arr.length} results`);
|
||||
const ips = await Promise.all(
|
||||
arr.map((obj) => dnsResolverA(logger, obj.name))
|
||||
);
|
||||
return ips.flat();
|
||||
}
|
||||
catch (err) {
|
||||
logger.info({err}, `SRV Error resolving ${hostname}`);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
module.exports = Regbot;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const regbots = [];
|
||||
const carriers = [];
|
||||
const gateways = [];
|
||||
|
||||
const getCountSuccessfulRegbots = () => regbots.filter((rb) => rb.status === 'registered').length;
|
||||
|
||||
function pickRelevantCarrierProperties(c) {
|
||||
return {
|
||||
@@ -32,6 +33,7 @@ function pickRelevantCarrierProperties(c) {
|
||||
register_public_ip_in_contact: c.register_public_ip_in_contact,
|
||||
outbound_sip_proxy: c.outbound_sip_proxy,
|
||||
account_sid: c.account_sid,
|
||||
trunk_type: c.trunk_type || 'static_ip'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,6 +93,14 @@ module.exports = async(logger, srf) => {
|
||||
active: false
|
||||
};
|
||||
|
||||
srf.locals.regbotStatus = () => {
|
||||
return {
|
||||
total: regbots.length,
|
||||
registered: getCountSuccessfulRegbots(),
|
||||
active: srf.locals.regbot.active
|
||||
};
|
||||
};
|
||||
|
||||
/* Set the Local SIP domain on srf.locals */
|
||||
await getLocalSIPDomain(logger, srf); // Initial Setup
|
||||
setInterval(getLocalSIPDomain, 300000, logger, srf); //Refresh SIP Domain every 5 mins
|
||||
@@ -209,11 +219,10 @@ const updateCarrierRegbots = async(logger, srf) => {
|
||||
}
|
||||
}
|
||||
if (JSON.stringify(gws) !== JSON.stringify(gateways)) hasChanged = true;
|
||||
|
||||
if (hasChanged) {
|
||||
|
||||
debug('updateCarrierRegbots: got new or changed carriers');
|
||||
logger.info('updateCarrierRegbots: got new or changed carriers');
|
||||
logger.info({gws}, 'updateCarrierRegbots: got new or changed carriers');
|
||||
carriers.length = 0;
|
||||
Array.prototype.push.apply(carriers, cs);
|
||||
|
||||
@@ -248,7 +257,8 @@ const updateCarrierRegbots = async(logger, srf) => {
|
||||
from_user: gw.carrier.register_from_user,
|
||||
from_domain: gw.carrier.register_from_domain,
|
||||
use_public_ip_in_contact: gw.carrier.register_public_ip_in_contact,
|
||||
outbound_sip_proxy: gw.carrier.outbound_sip_proxy
|
||||
outbound_sip_proxy: gw.carrier.outbound_sip_proxy,
|
||||
trunk_type: gw.carrier.trunk_type
|
||||
});
|
||||
regbots.push(rb);
|
||||
rb.start(srf);
|
||||
|
||||
Reference in New Issue
Block a user