UNPKG

domotz-remote-pawn

Version:

Domotz Agent

163 lines (146 loc) 5.29 kB
/** * This file is part of Domotz Agent. * * @license * 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/>. * * @requires sandbox/library/device * @requires sandbox/library/logger * @requires sandbox/library/crypto * @requires sandbox/library/buffer * @copyright Copyright (C) Domotz Inc */ const deviceLibrary = require('./library/device'); const domotzContext = require('./context'); const logger = require('./library/logger').logger; const util = require('util'); const vm = require('vm'); const driverTypes = require('./constants').driverTypes; const errorTypes = require('./constants').errorTypes; const rttOffset = 5000; var newConsole = null; var startTime = null; var agentDriverSettings = null; function failure(errorType) { if (!errorType || !(errorType in errorTypes)) { newConsole.warning('Error type %s is not recognized, converting to generic error', errorType); errorType = errorTypes.GENERIC_ERROR; } process.send({ outcome: 'failure', errorType: errorType, log: newConsole.get(), elapsed: new Date() - startTime, }); } function successConfigurationManagement(configurationData) { newConsole.debug('Success called'); process.send({ outcome: 'success', configurationData: configurationData, log: newConsole.get(), elapsed: new Date() - startTime, }); } function successGeneric(variables, table) { newConsole.debug('Success called'); var tables; // In case the user passes the table object as first argument if (!table && variables && variables.isTable) { tables = [variables.getResult()]; variables = null; } if (table && table.isTable) { tables = [table.getResult()]; } if (variables !== null && variables !== undefined) { validateVariables(variables); } process.send({ outcome: 'success', variables: variables, tables: tables, log: newConsole.get(), elapsed: new Date() - startTime, }); } function validateVariables(variables) { var uids = []; for (var i = 0; i < variables.length; i++) { var uid = variables[i].uid; if (uids.indexOf(uid) > -1) { newConsole.error('Duplicate variable uid received: ' + uid); failure('PARSING_ERROR'); return; } uids.push(uid); } } function timeoutReached() { newConsole.warning('Timeout expired'); failure(errorTypes.TIMEOUT_ERROR); } function buildDomotzContext(message, newConsole) { var context = domotzContext.createDomotzContext(message, newConsole); context.failure = failure; if (message.driverType === driverTypes.CONFIGURATION_MANAGEMENT) { context.success = successConfigurationManagement; } else if (message.driverType === driverTypes.GENERIC) { context.success = successGeneric; } else { context.success = successGeneric; } return context; } process.on('message', function (message) { agentDriverSettings = message.agentDriverSettings; newConsole = logger(message.logLevel || 'info', agentDriverSettings.max_log_entries); var context = vm.createContext({ D: buildDomotzContext(message, newConsole), import: function () { newConsole.error('Error: Import not possible in sandbox'); failure(errorTypes.IMPORT_NOT_ALLOWED); }, require: function () { newConsole.error('Error: Require not possible in sandbox'); failure(errorTypes.REQUIRE_NOT_ALLOWED); }, console: newConsole, }); // ToDo: check if this should not be included in the D context directly if (message.device) { context.D.device = deviceLibrary.device(message.device, agentDriverSettings, newConsole); newConsole.debug('Created new device for script execution: %s', util.inspect(message.device)); } const script = new vm.Script(message.script); var timeout = message.timeout || 5000; setTimeout(timeoutReached, timeout + rttOffset); startTime = new Date(); script.runInContext(context, { displayErrors: true, fileName: 'custom script', lineOffset: 0, timeout: timeout, }); }); process.on('uncaughtException', function (err) { var errorText = err.toString(); if (errorText.indexOf('timed out') !== -1) { newConsole.error('Script Execution timed out after: ' + (new Date() - startTime) + ' ms'); failure(errorTypes.TIMEOUT_ERROR); } else { newConsole.error('Caught exception: ' + errorText + '\n' + err.stack); failure(errorTypes.GENERIC_ERROR); } });