UNPKG

domotz-remote-pawn

Version:

Domotz Agent

191 lines (168 loc) 7.76 kB
/** This file is part of Domotz Agent. * Copyright (C) 2020 Domotz UK LLP * * 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/>. **/ var GETNEXT_HARD_TIMEOUT_SETTING = 'configuration.settings.snmp.hard_timeout.getNext'; var DEFAULT_GETNEXT_HARD_TIMEOUT_VALUE = 12000; var GETNEXT_SOFT_TIMEOUT_SETTING = 'configuration.settings.snmp.soft_timeout.getNext'; var DEFAULT_GETNEXT_SOFT_TIMEOUT_VALUE = 5000; var TimedSnmpSession = require('./timedSnmpSession'); var snmpNext = function (message, resourceLocator) { var snmp = resourceLocator.netSnmp; var cmdUtils = resourceLocator.utils.command; var snmpCommon = resourceLocator.snmpCommon; var async = resourceLocator.async; var settingsManager = resourceLocator.settingsManager; var myConsole = resourceLocator.log.decorateLogs(); var cid = message.correlationId; var options = message.payload; var host = cmdUtils.extractFromOptions(options, 'host', 'localhost'); var hardTimeout = parseInt(settingsManager.getSetting(GETNEXT_HARD_TIMEOUT_SETTING, DEFAULT_GETNEXT_HARD_TIMEOUT_VALUE)); var softTimeout = parseInt(settingsManager.getSetting(GETNEXT_SOFT_TIMEOUT_SETTING, DEFAULT_GETNEXT_SOFT_TIMEOUT_VALUE)); options.timeout = options.timeout || softTimeout; myConsole.debug('Hard Timeout %s, Soft Timeout %s ', hardTimeout, options.timeout); var oids = options.oids; delete options.oids; myConsole.debug('(%s): Start with oids: %s', cid, oids.toString()); function extractOidResponse(oidCheck, response) { myConsole.debug('(%s) - (%s)(%s): Got response', host, cid, oidCheck); if (!response || response.length === 0) { return {}; } var value = response[0]; var oid = value.oid; var valid = false; if (!snmp.isVarbindError(value)) { if (oid.startsWith(oidCheck)) { myConsole.verbose('(%s) - (%s): - MATCHING SNMP value retrieved (%s): %s', host, cid, oidCheck, oid); valid = true; } else { myConsole.verbose('(%s) - (%s): - UN-MATCHING SNMP value retrieved (%s): %s', host, cid, oidCheck, oid); } } else { myConsole.warn('(%s) - (%s): ERROR SNMP get - error retrieving oid: %s => varbind error: s', host, cid, oid, snmp.varbindError(value)); } return { valid: valid, oid: oid, oidRoot: oidCheck, }; } function setInvalid(oid) { myConsole.debug('(%s): Set oid invalid', oid); return { valid: false, oidRoot: oid, }; } return { execute: function (callback, authProvider) { myConsole.debug( 'SNMP_NEXT - (%s): Start executing SNMP next request to host %s for oids: %s, with options %s', cid, host, JSON.stringify(oids), JSON.stringify(options) ); var f = function (options, resourceLocator, host, oid, cb) { try { var bindings = snmpCommon.getInterfaceBindings(options, resourceLocator); var snmpSession = null; try { snmpSession = snmpCommon.getSession(bindings, host, options, authProvider); } catch (error) { callback({ error: error.toString() }); return; } var timedSnmpSession = new TimedSnmpSession(snmpSession, { host: host, oids: oids }, myConsole); snmpSession.on('error', function (error) { var errorMessage = error.toString(); myConsole.error('(socket error) %s', errorMessage); try { snmpSession.close(); } catch (error) { myConsole.error('cannot close session: ' + error); cb(null); } }); timedSnmpSession.getNext( [oid], function (error, response) { if (error) { if (response && response.error && response.error.stack) { delete response.error.stack; } myConsole.debug('(%s) - (%s): ERROR in response: %s', host, cid, oid, error.toString()); cb(null, setInvalid(oid)); } else if (response !== null && response !== undefined) { cb(null, extractOidResponse(oid, response)); } else { myConsole.debug('(%s) - (%s)(%s): ERROR no response', host, cid, oid); cb(null, setInvalid(oid)); } try { snmpSession.close(); } catch (error) { myConsole.error('cannot close session: ' + error); } }, hardTimeout ); } catch (e) { cb(null); } }; var allFunctions = []; var chunkSize = 1; // Most conservative choice, on each host doing all oids in series var chunks = []; for (var i = 0; i < oids.length; i += chunkSize) { chunks.push(oids.slice(i, i + chunkSize)); } chunks.forEach(function (tempoids) { var fChunk = function (cb) { var functions = []; for (var z = 0; z < tempoids.length; z++) { var oid = tempoids[z]; functions.push(f.bind(null, options, resourceLocator, host, oid)); } async.parallel(functions, function (err, results) { if (err !== null) { // This should not happen cb(err, results); } else { cb(null, results); } }); }; allFunctions.push(fChunk); }); async.series(allFunctions, function (err, results) { if (err !== null) { callback([]); } else { var totalResult = []; for (var i = 0; i < results.length; i++) { totalResult = totalResult.concat(results[i]); } callback(totalResult); } }); }, describe: function () { return cid + ' - SNMP_NEXT - ' + host + ' - ' + JSON.stringify(oids); }, }; }; module.exports.command = snmpNext;