mirror of
https://github.com/jambonz/sbc-sip-sidecar.git
synced 2026-10-04 02:04:20 +00:00
get correct expiry for multi-contact registraitons (#149)
This commit is contained in:
+48
-3
@@ -9,6 +9,7 @@ const {
|
||||
JAMBONES_REGBOT_REGISTER_FAILURE_THRESHOLD
|
||||
} = require('./config');
|
||||
const {isValidDomainOrIP, isValidIPv4} = require('./utils');
|
||||
const parseUri = require('drachtio-srf').parseUri;
|
||||
const DEFAULT_EXPIRES = (parseInt(JAMBONES_REGBOT_DEFAULT_EXPIRES_INTERVAL) || 3600);
|
||||
const MIN_EXPIRES = (parseInt(JAMBONES_REGBOT_MIN_EXPIRES_INTERVAL) || 90);
|
||||
const FAILURE_RETRY_INTERVAL = (parseInt(JAMBONES_REGBOT_FAILURE_RETRY_INTERVAL) || 300);
|
||||
@@ -17,6 +18,38 @@ const assert = require('assert');
|
||||
const version = require('../package.json').version;
|
||||
const useragent = JAMBONES_REGBOT_USER_AGENT || `Jambonz ${version}`;
|
||||
|
||||
/**
|
||||
* A 200 OK to a REGISTER may echo back every Contact bound to the AoR, not just ours
|
||||
* (e.g. when another device is registered against the same account). Per RFC 3261 10.2.4
|
||||
* we must refresh based on the expires of *our own* binding, so locate the returned Contact
|
||||
* whose user and host match the Contact we sent.
|
||||
* Returns the parsed expires (a number) of our binding, or undefined if it can't be matched.
|
||||
*/
|
||||
const getOwnContactExpires = (contacts, ownContactUri) => {
|
||||
let own;
|
||||
try {
|
||||
own = parseUri(ownContactUri);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
if (!own || !own.host) return undefined;
|
||||
const ownUser = own.user;
|
||||
const ownHost = own.host.toLowerCase();
|
||||
for (const c of contacts) {
|
||||
let u;
|
||||
try {
|
||||
u = parseUri(c.uri);
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
if (u && u.user === ownUser && (u.host || '').toLowerCase() === ownHost &&
|
||||
c.params && c.params.expires !== undefined) {
|
||||
return parseInt(c.params.expires);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
class Regbot {
|
||||
constructor(logger, opts) {
|
||||
this.logger = logger;
|
||||
@@ -235,9 +268,18 @@ class Regbot {
|
||||
}
|
||||
|
||||
if (res.has('Contact')) {
|
||||
const contact = res.getParsedHeader('Contact');
|
||||
if (contact.length > 0 && contact[0].params && contact[0].params.expires) {
|
||||
expires = parseInt(contact[0].params.expires);
|
||||
const contacts = res.getParsedHeader('Contact');
|
||||
const ownExpires = getOwnContactExpires(contacts, `${scheme}:${contactAddress}`);
|
||||
if (typeof ownExpires === 'number' && !isNaN(ownExpires)) {
|
||||
// refresh based on our own binding's expires
|
||||
expires = ownExpires;
|
||||
} else if (contacts.length === 1 && contacts[0].params && contacts[0].params.expires) {
|
||||
// single binding returned: safe to use even if the registrar rewrote the contact host
|
||||
expires = parseInt(contacts[0].params.expires);
|
||||
} else if (contacts.length > 1) {
|
||||
this.logger.info({aor: this.aor, ipv4: this.ipv4, port: this.port},
|
||||
// eslint-disable-next-line max-len
|
||||
`200 OK returned ${contacts.length} contacts but none matched our own binding; using expires ${expires}`);
|
||||
}
|
||||
} else {
|
||||
this.logger.debug({ aor: this.aor, ipv4: this.ipv4, port: this.port },
|
||||
@@ -355,5 +397,8 @@ const dnsResolverSrv = async(logger, hostname, transport) => {
|
||||
};
|
||||
|
||||
|
||||
// exposed for unit testing
|
||||
Regbot._getOwnContactExpires = getOwnContactExpires;
|
||||
|
||||
module.exports = Regbot;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user