domotz-remote-pawn
Version:
Domotz Agent
186 lines (163 loc) • 6.67 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 Iacopo Papalini <ipapalini@domotz.com> on 10/09/15.
*/
const MODULE_NAME = 'SPEED_TEST';
const KILL_CHILD_TIMEOUT = 300000;
var lockSeed = Math.random();
var speedTest = function (message, resourceLocator) {
const md5 = resourceLocator.utils.random.md5;
const time = resourceLocator.utils.time;
const mutex = resourceLocator.utils.mutex;
const fork = resourceLocator.utils.proc.fork;
const join = resourceLocator.path.join;
const engineClient = resourceLocator.engineRequest;
const ndtServers = resourceLocator.networkTools.ndtServers;
const speedTest = resourceLocator.networkTools.speedTest;
const ooklaServers = resourceLocator.networkTools.ooklaServers;
const configuration = resourceLocator.configuration;
const cid = message.correlationId || 'From API';
const serverId = message.payload.server_id;
const nonInteractive = message.non_interactive;
var modulePath = join(__dirname, '..', '..', 'network_tools', 'ooklaSpeedTest.js');
var call = internal() ? callInternalTest : callExternalTest;
var lockId = md5(lockSeed.toString());
function lock() {
return mutex.lock(MODULE_NAME, lockId);
}
function unlock() {
mutex.unlock(MODULE_NAME, lockId);
}
var results = {
stats: {
start: new Date(),
end: null,
elapsed_milliseconds: null
},
speedTest: {}
};
function copyResults(ndtInfo) {
results.stats.end = new Date();
results.stats.elapsed_milliseconds = time.getDiff(results.stats);
results.speedTest = speedTest.ndtInfoIntoDTO(ndtInfo);
return speedTest.filterItems(ndtInfo);
}
function processData(data, cb) {
if (data.blacklist && data.blacklist.length > 0) {
console.warn("%s - (%s): Blacklist servers => %s", MODULE_NAME, cid,
JSON.stringify(data.blacklist));
ooklaServers.blacklistServers(data.blacklist);
}
if (!data.error) {
if (data.server) {
/* store it as preferred server to perform the interactive speed test */
ooklaServers.setServerAsPreferred(data.server);
}
console.debug("%s - (%s): Speed test success", MODULE_NAME, cid);
var items = copyResults(data.result);
cb(results);
engineClient.sendWithPromise('/network/speed-test', 'POST', items);
} else {
console.debug("%s - (%s): Speed test failure => %s", MODULE_NAME, cid,
data.error);
cb(data.error, data.error);
}
}
function callExternalTest(msg, cb) {
var child = fork(modulePath, [], {silent: false});
var killChildTimeout = setTimeout(function () {
console.info("%s - (%s) killing child process by timeout", MODULE_NAME, cid);
child.kill();
unlock();
}, KILL_CHILD_TIMEOUT);
child.send(msg);
child.on('message', function (data) {
clearTimeout(killChildTimeout);
processData(data, cb);
child.kill();
unlock();
});
}
function callInternalTest(msg, cb) {
var ooklaSpeedTest = require(modulePath);
ooklaSpeedTest.main(msg, function(data) {
processData(data, cb);
unlock();
});
}
return {
describe: function () {
return cid + " - " + MODULE_NAME;
},
execute: function (callback) {
if (!lock()) {
var msg = MODULE_NAME + ' - (' + cid + '): Another Speed test is currently running';
console.warn(msg);
return callback(null, {
status: 409,
message: msg
});
}
if (!ooklaEnabled(configuration)) {// NDT test
ndtServers.findById(serverId)
.then(speedTest.performSpeedTest)
.then(copyResults)
.then(function (items) {
callback(results);
return engineClient.sendWithPromise('/network/speed-test', 'POST', items);
})
.catch(function (err) {
callback(null, err);
}).finally(function () {
unlock();
});
} else if (nonInteractive) {
console.info("%s (%s): Not interactive mode, selecting N closest servers", MODULE_NAME, cid);
ooklaServers.getNearestServers()
.then(function (serverList) {
console.info("%s - (%s): Nearest Server: %s",
MODULE_NAME, cid, JSON.stringify(serverList));
var msg = {
bestServer: null,
serverList: serverList
};
call(msg, callback);
});
} else {
console.info("%s - (%s): interactive mode, searching for %s", MODULE_NAME, cid, serverId);
ooklaServers.findById(serverId)
.then(function (server) {
console.info("%s - (%s): found server: %s",
MODULE_NAME, cid, JSON.stringify(server));
var msg = {bestServer: server, serverList: null};
call(msg, callback);
});
}
}
};
};
module.exports.command = speedTest;
function internal() {
var env = process.env;
return (env.DPLATFORM === 'openwrt' || env.DARCHITECTURE === 'x64');
}
function ooklaEnabled(configuration) {
return (typeof configuration.enable_ookla === 'undefined') ?
true : configuration.enable_ookla;
}