domotz-remote-pawn
Version:
Domotz Agent
133 lines (124 loc) • 4.69 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
*
*
* Created by Tommaso Latini <tlatini@domotz.com> on 14/09/15.
*/
var factory = function (interfacesBindingStorage, host, resourceLocator) {
var myConsole = resourceLocator.log.decorateLogs();
var hostInfo = resourceLocator.discovery.host;
function getIP(addresses) {
var ipAddr;
for (var j = 0; j < addresses.length; j++) {
ipAddr = addresses[j].$;
if (ipAddr.addrtype === 'ipv4') {
return ipAddr.addr;
}
}
}
function parseHost(device) {
var addresses = device.address,
status = device.status[0].$,
hostname = device.hostnames[0],
reason = status.reason,
name = hostname.trim && hostname.trim() === '' ? '' : hostname.hostname[0].$.name,
ip,
mac = null,
addr;
switch (reason) {
case 'arp-response':
for (var i = 0; i < addresses.length; i++) {
addr = addresses[i].$;
if (addr.addrtype === 'ipv4') {
ip = addr.addr;
} else if (addr.addrtype === 'mac') {
mac = addr.addr;
}
}
break;
case 'echo-reply':
case 'syn-ack':
case 'udp-response':
ip = getIP(addresses);
break;
case 'conn-refused':
ip = getIP(addresses);
if (!host.IPisInCustomSubnet(ip)) {
myConsole.info('Unsupported reason conn-refused for internal hosts: %s', ip);
return null;
} else {
myConsole.debug('Reason conn-refused for ext hosts %s', ip);
}
break;
case 'localhost-response':
myConsole.verbose('Unsupported reason: %s', reason);
break;
case 'reset':
case 'timestamp-reply':
var externalDevice = [
{
ip: getIP(addresses),
},
];
if (hostInfo.deviceBelongsToExternalHosts(externalDevice) || hostInfo.deviceBelongsToExternalSubnet(externalDevice)) {
myConsole.info('accept reason: %s for external/routed hosts', reason);
ip = getIP(addresses);
}
break;
default:
myConsole.warn('Unsupported reason: %s %s', reason, (ip = getIP(addresses)));
return null;
}
if (!ip) {
return null;
}
/* If the host belongs to the list of external hosts we must use the mac address defined in the agent's
settings */
var forcedMacAddress = host.getExternalHostMac(ip);
if (forcedMacAddress) {
mac = forcedMacAddress;
}
return interfacesBindingStorage.getDevice(ip, mac, name, forcedMacAddress);
}
function parse(result) {
var ret = {};
try {
var hosts = result.nmaprun.host || [];
for (var i = 0; i < hosts.length; i++) {
var device = parseHost(hosts[i]);
if (device) {
var mac = device.mac;
if (mac) {
var dp = interfacesBindingStorage.deviceProjection(device);
if (ret[mac] === undefined) {
ret[mac] = [dp];
} else {
ret[mac].push(dp);
}
}
}
}
return ret;
} catch (err) {
myConsole.warn(err.stack);
throw new Error('Error during parsing: Wrong Input');
}
}
return {
parse: parse,
};
};
module.exports.factory = factory;