2016-02-16 00:56:05 +00:00
|
|
|
/* jslint node: true */
|
|
|
|
'use strict';
|
|
|
|
|
2017-03-09 05:37:02 +00:00
|
|
|
const _ = require('lodash');
|
2016-02-16 00:56:05 +00:00
|
|
|
|
|
|
|
const FTN_ADDRESS_REGEXP = /^([0-9]+:)?([0-9]+)(\/[0-9]+)?(\.[0-9]+)?(@[a-z0-9\-\.]+)?$/i;
|
|
|
|
const FTN_PATTERN_REGEXP = /^([0-9\*]+:)?([0-9\*]+)(\/[0-9\*]+)?(\.[0-9\*]+)?(@[a-z0-9\-\.\*]+)?$/i;
|
|
|
|
|
|
|
|
module.exports = class Address {
|
|
|
|
constructor(addr) {
|
|
|
|
if(addr) {
|
|
|
|
if(_.isObject(addr)) {
|
|
|
|
Object.assign(this, addr);
|
|
|
|
} else if(_.isString(addr)) {
|
|
|
|
const temp = Address.fromString(addr);
|
|
|
|
if(temp) {
|
|
|
|
Object.assign(this, temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-13 15:57:54 +00:00
|
|
|
static isValidAddress(addr) {
|
|
|
|
return addr && addr.isValid();
|
|
|
|
}
|
|
|
|
|
|
|
|
isValid() {
|
|
|
|
// FTN address is valid if we have at least a net/node
|
|
|
|
return _.isNumber(this.net) && _.isNumber(this.node);
|
|
|
|
}
|
|
|
|
|
2016-02-16 00:56:05 +00:00
|
|
|
isEqual(other) {
|
|
|
|
if(_.isString(other)) {
|
|
|
|
other = Address.fromString(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
this.net === other.net &&
|
|
|
|
this.node === other.node &&
|
|
|
|
this.zone === other.zone &&
|
|
|
|
this.point === other.point &&
|
|
|
|
this.domain === other.domain
|
2017-02-20 18:31:24 +00:00
|
|
|
);
|
2016-02-16 00:56:05 +00:00
|
|
|
}
|
|
|
|
|
2016-02-17 05:11:55 +00:00
|
|
|
getMatchAddr(pattern) {
|
2016-02-16 00:56:05 +00:00
|
|
|
const m = FTN_PATTERN_REGEXP.exec(pattern);
|
|
|
|
if(m) {
|
|
|
|
let addr = { };
|
|
|
|
|
|
|
|
if(m[1]) {
|
2017-02-20 18:31:24 +00:00
|
|
|
addr.zone = m[1].slice(0, -1);
|
2016-02-16 00:56:05 +00:00
|
|
|
if('*' !== addr.zone) {
|
|
|
|
addr.zone = parseInt(addr.zone);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addr.zone = '*';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m[2]) {
|
|
|
|
addr.net = m[2];
|
|
|
|
if('*' !== addr.net) {
|
|
|
|
addr.net = parseInt(addr.net);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addr.net = '*';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m[3]) {
|
|
|
|
addr.node = m[3].substr(1);
|
|
|
|
if('*' !== addr.node) {
|
|
|
|
addr.node = parseInt(addr.node);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addr.node = '*';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m[4]) {
|
|
|
|
addr.point = m[4].substr(1);
|
|
|
|
if('*' !== addr.point) {
|
|
|
|
addr.point = parseInt(addr.point);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addr.point = '*';
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m[5]) {
|
|
|
|
addr.domain = m[5].substr(1);
|
|
|
|
} else {
|
|
|
|
addr.domain = '*';
|
|
|
|
}
|
|
|
|
|
2016-02-17 05:11:55 +00:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
getMatchScore(pattern) {
|
|
|
|
let score = 0;
|
|
|
|
const addr = this.getMatchAddr(pattern);
|
|
|
|
if(addr) {
|
|
|
|
const PARTS = [ 'net', 'node', 'zone', 'point', 'domain' ];
|
|
|
|
for(let i = 0; i < PARTS.length; ++i) {
|
|
|
|
const member = PARTS[i];
|
|
|
|
if(this[member] === addr[member]) {
|
|
|
|
score += 2;
|
|
|
|
} else if('*' === addr[member]) {
|
|
|
|
score += 1;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return score;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2016-03-09 05:30:04 +00:00
|
|
|
isPatternMatch(pattern) {
|
2016-02-17 05:11:55 +00:00
|
|
|
const addr = this.getMatchAddr(pattern);
|
|
|
|
if(addr) {
|
2016-02-16 00:56:05 +00:00
|
|
|
return (
|
|
|
|
('*' === addr.net || this.net === addr.net) &&
|
|
|
|
('*' === addr.node || this.node === addr.node) &&
|
|
|
|
('*' === addr.zone || this.zone === addr.zone) &&
|
|
|
|
('*' === addr.point || this.point === addr.point) &&
|
|
|
|
('*' === addr.domain || this.domain === addr.domain)
|
2017-02-20 18:31:24 +00:00
|
|
|
);
|
2016-02-16 00:56:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static fromString(addrStr) {
|
|
|
|
const m = FTN_ADDRESS_REGEXP.exec(addrStr);
|
|
|
|
|
|
|
|
if(m) {
|
|
|
|
// start with a 2D
|
|
|
|
let addr = {
|
|
|
|
net : parseInt(m[2]),
|
|
|
|
node : parseInt(m[3].substr(1)),
|
|
|
|
};
|
|
|
|
|
|
|
|
// 3D: Addition of zone if present
|
|
|
|
if(m[1]) {
|
|
|
|
addr.zone = parseInt(m[1].slice(0, -1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4D if optional point is present
|
|
|
|
if(m[4]) {
|
|
|
|
addr.point = parseInt(m[4].substr(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
// 5D with @domain
|
|
|
|
if(m[5]) {
|
|
|
|
addr.domain = m[5].substr(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Address(addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(dimensions) {
|
|
|
|
dimensions = dimensions || '5D';
|
|
|
|
|
|
|
|
let addrStr = `${this.zone}:${this.net}`;
|
|
|
|
|
|
|
|
// allow for e.g. '4D' or 5
|
|
|
|
const dim = parseInt(dimensions.toString()[0]);
|
|
|
|
|
|
|
|
if(dim >= 3) {
|
|
|
|
addrStr += `/${this.node}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// missing & .0 are equiv for point
|
|
|
|
if(dim >= 4 && this.point) {
|
|
|
|
addrStr += `.${this.point}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(5 === dim && this.domain) {
|
|
|
|
addrStr += `@${this.domain.toLowerCase()}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return addrStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static getComparator() {
|
|
|
|
return function(left, right) {
|
|
|
|
let c = (left.zone || 0) - (right.zone || 0);
|
|
|
|
if(0 !== c) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = (left.net || 0) - (right.net || 0);
|
|
|
|
if(0 !== c) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = (left.node || 0) - (right.node || 0);
|
|
|
|
if(0 !== c) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (left.domain || '').localeCompare(right.domain || '');
|
2017-02-20 18:31:24 +00:00
|
|
|
};
|
2016-02-16 00:56:05 +00:00
|
|
|
}
|
2017-02-20 18:31:24 +00:00
|
|
|
};
|