UNPKG

domotz-remote-pawn

Version:

Domotz Agent

159 lines (139 loc) 5.1 kB
/** 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/>. **/ /** * This module performs retries on stale bindings * Created by Andrea Azzara <a.azzara@domotz.com> on 13/07/18. */ const RETRY_TRIALS = 5; const RETRY_HOST_TIMEOUT = 10; module.exports.factory = function ( q, host, log, configuration, blacklist, interfacesBinding, async, lodash, bindDiscovery, nmapCommands, ip, ipUtils ) { 'use strict'; var iteration = 0; var baseConsole = log.decorateLogs(); var myConsole = baseConsole; function setIteration(i) { iteration = i; myConsole = baseConsole.decorate(String(iteration)); } setIteration(0); function getRetryInterval(conf) { var discovery = conf.discovery; return discovery && discovery.retry_interval ? discovery.retry_interval : 1000; } var retryInterval = getRetryInterval(configuration); function _getNmapType(iface) { if (!iface.custom) { return nmapCommands.NMAP_TYPE.DEFAULT; } if (iface.netmask === 32) { return nmapCommands.NMAP_TYPE.EXTERNAL_HOST; } return nmapCommands.NMAP_TYPE.EXTERNAL_SUBNET; } function retryOnStaleBindingsForAllInterfaces(callback) { var interfaceList = host.getAllowedInterfacesList(); async.each( interfaceList, function (iface, cb) { _retryOnStaleBindingsForSingleInterface(RETRY_TRIALS, iface, cb); }, function () { callback(); } ); } function _retryOnStaleBindingsForSingleInterface(count, iface, cb) { function pingDevices(retryCallback) { var staleDevices = _getStaleDevicesForInterface(iface); if (staleDevices.length === 0) { retryCallback(); return; } var nmapType = _getNmapType(iface); if (count % 2 !== 0 && nmapType === nmapCommands.NMAP_TYPE.DEFAULT) { nmapType = nmapCommands.NMAP_TYPE.DISABLE_ARP_PING; } myConsole.info('retryOnStaleBindingsAdvanced, there are %s stale devices, retry attempts left %s ', staleDevices.length, count); count--; bindDiscovery .discover(staleDevices, nmapType, RETRY_HOST_TIMEOUT, iface) .then(interfacesBinding.setFreshDiscoveredBindings) .then(function () { if (count === 0) { myConsole.info('Exiting retry loop, devices still stale: %d', staleDevices.length); retryCallback(); } else { retryCallback('continue'); } }) .catch(function (err) { myConsole.error('Discovery error %s', err.toString()); retryCallback(err); }); } async.retry({ times: count, interval: retryInterval }, pingDevices, function (err) { if (err) { myConsole.error('Terminating retries due to error: %s', err.message); } else { myConsole.verbose('retryOnStaleBindingsAdvanced END'); } cb(); }); } function _isIpInRanges(ipRanges, ip) { return ( ipRanges && lodash.some(ipRanges, function (ipRange) { return ipUtils.isIpInRange(ipRange, ip); }) ); } function _deviceBelongsToInterface(device, iface) { return ipUtils.isIpInList(iface.ipList, device.ip) || _isIpInRanges(iface.ipRange, device.ip); } function _getStaleDevicesForInterface(iface) { var staleList = interfacesBinding.listStale(); var devicesToExclude = blacklist.getDeviceToExclude(); var filteredStaleDevices = staleList.filter(function (e) { return devicesToExclude.indexOf(e.ip) < 0; }); return lodash .filter(filteredStaleDevices, function (device) { return _deviceBelongsToInterface(device, iface); }) .map(function (e) { return e.ip; }); } return { retryOnStaleBindingsForAllInterfaces: retryOnStaleBindingsForAllInterfaces, setIteration: setIteration, }; };