knxultimate
Version:
KNX IP protocol implementation for Node. This is the ENGINE of Node-Red KNX-Ultimate node.
114 lines • 4.42 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getIPv4Interfaces = getIPv4Interfaces;
exports.getLocalAddress = getLocalAddress;
const utils_1 = require("../utils");
const KnxLog_1 = require("../KnxLog");
const os_1 = __importDefault(require("os"));
const logger = (0, KnxLog_1.module)('ipAddressHelper');
function getIPv4Interfaces() {
const candidateInterfaces = {};
let interfaces;
if (process.env.CI && process.env.KNX_USE_FAKE_IFACE) {
interfaces = {
eth0: [
{
address: '192.168.1.58',
netmask: '255.255.255.0',
family: 'IPv4',
mac: '00:00:00:00:00:00',
internal: false,
cidr: '192.168.1.58/24',
},
],
};
}
else {
try {
interfaces = os_1.default.networkInterfaces();
}
catch (e) {
logger.error('getIPv4Interfaces: os.networkInterfaces failed: %s', e?.message || e);
throw e;
}
}
for (const iface in interfaces) {
for (let index = 0; index < interfaces[iface].length; index++) {
let intf;
try {
intf = interfaces[iface][index];
if (intf === undefined) {
logger.debug('intf is null: control point 1');
}
else {
logger.debug('parsing interface: %s (%j)', iface, intf);
if (intf.family !== undefined &&
(intf.family.toString().includes('4') ||
intf.family === 4) &&
!intf.internal) {
logger.debug('Found suitable interface: %s (%j)', iface, intf);
candidateInterfaces[iface] = intf;
}
else {
logger.debug('Found NOT suitable interface: %s (%j)', iface, intf);
}
}
}
catch (error) {
logger.error('getIPv4Interfaces: error parsing the interface %s (%j)', iface, intf);
}
}
}
return candidateInterfaces;
}
function getLocalAddress(_interface = '') {
logger.debug('getLocalAddress: getting interfaces');
const candidateInterfaces = getIPv4Interfaces();
const requested = _interface || '';
if (requested !== '') {
if (!(0, utils_1.hasProp)(candidateInterfaces, requested)) {
logger.error(`exports.getLocalAddress: Interface ${requested} not found or has no useful IPv4 address!`);
throw Error(`Interface ${requested} not found or has no useful IPv4 address!`);
}
return candidateInterfaces[requested].address;
}
const entries = Object.entries(candidateInterfaces);
if (entries.length === 0)
throw Error('No valid IPv4 interfaces detected');
const isRfc1918 = (ip) => {
return (ip.startsWith('10.') ||
ip.startsWith('192.168.') ||
(ip.startsWith('172.') &&
(() => {
const n = parseInt(ip.split('.')[1] || '0', 10);
return n >= 16 && n <= 31;
})()));
};
const isApipa = (ip) => ip.startsWith('169.254.');
const looksVirtual = (name) => /(^|\b)(vnic|vmnet|utun|awdl|bridge|br-|vboxnet|docker|tap|zt|lo|gif|stf|ap|llw)/i.test(name);
const looksPhysical = (name) => /^(en\d+|eth\d+|wlan\d+|wlx\w+)/i.test(name) ||
/wi-?fi|ethernet/i.test(name);
const score = (name, ip) => {
let s = 0;
if (looksPhysical(name))
s += 100;
if (isRfc1918(ip))
s += 40;
if (ip.startsWith('192.168.'))
s += 20;
if (looksVirtual(name))
s -= 200;
if (isApipa(ip))
s -= 500;
return s;
};
const best = entries
.map(([name, info]) => ({ name, info, s: score(name, info.address) }))
.sort((a, b) => b.s - a.s)[0];
logger.debug('Selected interface: %s (%j) with score %d', best.name, best.info, best.s);
return best.info.address;
}
//# sourceMappingURL=ipAddressHelper.js.map