1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-03-09 15:40:18 +00:00

Completed server load-balancing support

This commit is contained in:
Ylian Saint-Hilaire 2017-09-20 14:44:22 -07:00
parent 1031eca853
commit 453383f851
19 changed files with 305 additions and 56 deletions

View file

@ -26,7 +26,7 @@ function createMeshCore(agent) {
var lastNetworkInfo = null;
var lastPublicLocationInfo = null;
var selfInfoUpdateTimer = null;
obj.useNativePipes = (process.platform == 'win32');
obj.useNativePipes = true; //(process.platform == 'win32');
var http = require('http');
var fs = require('fs');
@ -158,7 +158,7 @@ function createMeshCore(agent) {
};
// Replace a string with a number if the string is an exact number
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) == x)) { x = parseInt(x); } return x; }
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) === x)) { x = parseInt(x); } return x; }
// Convert decimal to hex
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }
@ -218,16 +218,48 @@ function createMeshCore(agent) {
return results;
}
// Parge a URL string into an options object
function parseUrl(url) {
var x = url.split('/');
if (x.length < 4) return null;
var y = x[2].split(':');
var options = {};
var options = { protocol: x[0], hostname: y[0], path: '/' + x.splice(3).join('/') };
if (y.length == 1) { options.port = ((x[0] == 'https:') || (x[0] == 'wss:')) ? 443 : 80; } else { options.port = parseInt(y[1]); }
if (isNaN(options.port) == true) return null;
return options;
// Get server target url with a custom path
function getServerTargetUrl(path) {
var x = mesh.ServerUrl;
//sendConsoleText("mesh.ServerUrl: " + mesh.ServerUrl);
if (x == null) { return null; }
if (path == null) { path = ''; }
x = http.parseUri(x);
if (x == null) return null;
return x.protocol + '//' + x.host + ':' + x.port + '/' + path;
}
// Get server url. If the url starts with "*/..." change it, it not use the url as is.
function getServerTargetUrlEx(url) {
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
return url;
}
// Send a wake-on-lan packet
function sendWakeOnLan(hexMac) {
var count = 0;
try {
var interfaces = require('os').networkInterfaces();
var magic = 'FFFFFFFFFFFF';
for (var x = 1; x <= 16; ++x) { magic += hexMac; }
var magicbin = Buffer.from(magic, 'hex');
for (var adapter in interfaces) {
if (interfaces.hasOwnProperty(adapter)) {
for (var i = 0; i < interfaces[adapter].length; ++i) {
var addr = interfaces[adapter][i];
if ((addr.family == 'IPv4') && (addr.mac != '00:00:00:00:00:00')) {
var socket = require('dgram').createSocket({ type: "udp4" });
socket.bind({ address: addr.address });
socket.setBroadcast(true);
socket.send(magicbin, 7, "255.255.255.255");
count++;
}
}
}
}
} catch (e) { }
return count;
}
// Handle a mesh agent command
@ -245,21 +277,26 @@ function createMeshCore(agent) {
else if (data.type == 'tunnel') { // Process a new tunnel connection request
if (data.value && data.sessionid) {
// Create a new tunnel object
var tunnel = http.request(parseUrl(data.value));
tunnel.upgrade = onTunnelUpgrade;
tunnel.sessionid = data.sessionid;
tunnel.rights = data.rights;
tunnel.state = 0;
tunnel.url = data.value;
tunnel.protocol = 0;
//sendConsoleText(data.value);
var xurl = getServerTargetUrlEx(data.value);
//sendConsoleText(xurl);
if (xurl != null) {
var tunnel = http.request(http.parseUri(xurl));
tunnel.upgrade = onTunnelUpgrade;
tunnel.sessionid = data.sessionid;
tunnel.rights = data.rights;
tunnel.state = 0;
tunnel.url = xurl;
tunnel.protocol = 0;
// Put the tunnel in the tunnels list
var index = 1;
while (tunnels[index]) { index++; }
tunnel.index = index;
tunnels[index] = tunnel;
// Put the tunnel in the tunnels list
var index = 1;
while (tunnels[index]) { index++; }
tunnel.index = index;
tunnels[index] = tunnel;
sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
}
}
}
break;
@ -267,7 +304,7 @@ function createMeshCore(agent) {
case 'wakeonlan': {
// Send wake-on-lan on all interfaces for all MAC addresses in data.macs array. The array is a list of HEX MAC addresses.
sendConsoleText('Server requesting wake-on-lan for: ' + data.macs.join(', '));
// TODO!!!!
for (var i in data.macs) { sendWakeOnLan(data.macs[i]); }
break;
}
case 'poweraction': {
@ -554,7 +591,7 @@ function createMeshCore(agent) {
var response = null;
switch (cmd) {
case 'help': { // Displays available commands
response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, parseurl, httpget, wslist, wsconnect, wssend, wsclose, notify, ls, amt, netinfo, location, power.';
response = 'Available commands: help, info, args, print, type, dbget, dbset, dbcompact, parseuri, httpget, wslist, wsconnect, wssend, wsclose, notify, ls, amt, netinfo, location, power, wakeonlan.';
break;
}
case 'notify': { // Send a notification message to the mesh
@ -569,7 +606,7 @@ function createMeshCore(agent) {
break;
}
case 'info': { // Return information about the agent and agent core module
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nNative Pipes: ' + obj.useNativePipes + '.';
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nNative Pipes: ' + obj.useNativePipes + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
break;
}
case 'selfinfo': { // Return self information block
@ -628,10 +665,6 @@ function createMeshCore(agent) {
response = 'Database compacted: ' + r;
break;
}
case 'parseurl': {
response = objToString(parseUrl(args['_'][0]));
break;
}
case 'httpget': {
if (consoleHttpRequest != null) {
response = 'HTTP operation already in progress.';
@ -639,7 +672,7 @@ function createMeshCore(agent) {
if (args['_'].length != 1) {
response = 'Proper usage: httpget (url)';
} else {
var options = parseUrl(args['_'][0]);
var options = http.parseUri(args['_'][0]);
options.method = 'GET';
if (options == null) {
response = 'Invalid url.';
@ -648,7 +681,7 @@ function createMeshCore(agent) {
consoleHttpRequest.sessionid = sessionid;
if (consoleHttpRequest != null) {
consoleHttpRequest.end();
response = 'HTTPGET ' + options.protocol + '//' + options.hostname + ':' + options.port + options.path;
response = 'HTTPGET ' + options.protocol + '//' + options.host + ':' + options.port + options.path;
}
}
}
@ -670,7 +703,7 @@ function createMeshCore(agent) {
} else {
var httprequest = null;
try {
httprequest = http.request(parseUrl(args['_'][0]));
httprequest = http.request(http.parseUri(args['_'][0]));
} catch (e) { response = 'Invalid HTTP websocket request'; }
if (httprequest != null) {
httprequest.upgrade = onWebSocketUpgrade;
@ -756,7 +789,18 @@ function createMeshCore(agent) {
break;
}
case 'netinfo': { // Show network interface information
response = objToString(mesh.NetInfo, 0, '.');
//response = objToString(mesh.NetInfo, 0, '.');
var interfaces = require('os').networkInterfaces();
response = objToString(interfaces, 0, '.');
break;
}
case 'wakeonlan': { // Send wake-on-lan
if ((args['_'].length != 1) || (args['_'][0].length != 12)) {
response = 'Proper usage: wakeonlan [mac], for example "wakeonlan 010203040506".';
} else {
var count = sendWakeOnLan(args['_'][0]);
response = 'Sent wake-on-lan on ' + count + ' interface(s).';
}
break;
}
case 'sendall': { // Send a message to all consoles on this mesh
@ -782,6 +826,10 @@ function createMeshCore(agent) {
});
break;
}
case 'parseuri': {
response = JSON.stringify(http.parseUri(args['_'][0]));
break;
}
default: { // This is an unknown command, return an error message
response = 'Unknown command \"' + cmd + '\", type \"help\" for list of avaialble commands.';
break;