Workaround a race condition on meshagent sending coreinfo messages.

Ylian Saint-Hilaire committed Nov 25, 2018 at 12:59 UTC 532743dd1b13d0d8130d71002f7d983d9bb17d15
5 files changed +57 -59
agents/MeshAgentOSXPackager.zip
Binary files a/agents/MeshAgentOSXPackager.zip and b/agents/MeshAgentOSXPackager.zip differ
agents/meshcore.js
+54 -55
@@ -58,9 +58,10 @@ function createMeshCore(agent) {
58 */
59
60 // MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
61 - obj.meshCoreInfo = "MeshCore v6";
62 - obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
63 - obj.loggedInUsers = null;
61 + var meshCoreObj = { "action": "coreinfo", "value": "MeshCore v6", "caps": 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
62 +
63 + // Get the operating system description string
64 + try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; }); } catch (ex) { }
65
66 var meshServerConnectionState = 0;
67 var tunnels = {};
@@ -90,19 +91,15 @@ function createMeshCore(agent) {
91 childProcess = require('child_process');
92 if (mesh.hasKVM == 1) { // if the agent is compiled with KVM support
93 // Check if this computer supports a desktop
93 - try { if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support)) { obj.meshCoreCapabilities |= 1; } } catch (ex) { }
94 + try { if ((process.platform == 'win32') || (process.platform == 'darwin') || (require('monitor-info').kvm_x11_support)) { meshCoreObj.caps |= 1; } } catch (ex) { }
95 }
96 } else {
97 // Running in nodejs
97 - obj.meshCoreInfo += '-NodeJS';
98 - obj.meshCoreCapabilities = 8;
98 + meshCoreObj.value += '-NodeJS';
99 + meshCoreObj.caps = 8;
100 mesh = agent.getMeshApi();
101 }
102
102 - // Get the operating system description string
103 - var osDesc = null;
104 - try { require('os').name().then(function (v) { osDesc = v; if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "coreinfo", "value": obj.meshCoreInfo, "osdesc": osDesc }); } }); } catch (ex) { }
105 -
103 /*
104 var AMTScanner = require("AMTScanner");
105 var scan = new AMTScanner();
@@ -139,31 +136,33 @@ function createMeshCore(agent) {
136 // Fetch the SMBios Tables
137 var SMBiosTables = null;
138 var SMBiosTablesRaw = null;
142 - require('smbios').get(function (data) {
143 - if (data != null) {
144 - SMBiosTablesRaw = data;
145 - SMBiosTables = require('smbios').parse(data)
146 - if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "smbios", "value": SMBiosTablesRaw }); }
139 + try {
140 + require('smbios').get(function (data) {
141 + if (data != null) {
142 + SMBiosTablesRaw = data;
143 + SMBiosTables = require('smbios').parse(data)
144 + if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "smbios", "value": SMBiosTablesRaw }); }
145
148 - // If SMBios tables say that AMT is present, try to connect MEI
149 - if (SMBiosTables.amtInfo && (SMBiosTables.amtInfo.AMT == true)) {
150 - // Try to load up the MEI module
151 - try {
152 - var amtMeiLib = require('amt-mei');
153 - amtMei = new amtMeiLib();
154 - amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; });
155 - amtMeiConnected = 2;
156 - sendPeriodicServerUpdate(1);
157 - } catch (ex) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
146 + // If SMBios tables say that AMT is present, try to connect MEI
147 + if (SMBiosTables.amtInfo && (SMBiosTables.amtInfo.AMT == true)) {
148 + // Try to load up the MEI module
149 + try {
150 + var amtMeiLib = require('amt-mei');
151 + amtMei = new amtMeiLib();
152 + amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; });
153 + amtMeiConnected = 2;
154 + sendPeriodicServerUpdate(1);
155 + } catch (ex) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
156 + }
157 }
159 - }
160 - });
158 + });
159 + } catch (ex) { sendConsoleText(ex); }
160
161 // Try to load up the WIFI scanner
162 try {
163 var wifiScannerLib = require('wifi-scanner');
164 wifiScanner = new wifiScannerLib();
166 - wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); });
165 + wifiScanner.on('accessPoint', function (data) { sendConsoleText(data); });
166 } catch (ex) { wifiScannerLib = null; wifiScanner = null; }
167
168 // Get our location (lat/long) using our public IP address
@@ -931,8 +930,8 @@ function createMeshCore(agent) {
930 case 'border':
931 {
932 if ((args['_'].length == 1) && (args['_'][0] == 'on')) {
934 - if (obj.loggedInUsers.length > 0) {
935 - obj.borderManager.Start(obj.loggedInUsers[0]);
933 + if (meshCoreObj.users.length > 0) {
934 + obj.borderManager.Start(meshCoreObj.users[0]);
935 response = 'Border blinking is on.';
936 } else {
937 response = 'Cannot turn on border blinking, no logged in users.';
@@ -946,11 +945,10 @@ function createMeshCore(agent) {
945 }
946 break;
947 */
949 - case 'users':
950 - {
951 - if (obj.loggedInUsers == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + obj.loggedInUsers.join(', ') + '.'; }
952 - }
948 + case 'users': {
949 + if (meshCoreObj.users == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + meshCoreObj.users.join(', ') + '.'; }
950 break;
951 + }
952 case 'toast': {
953 if (process.platform == 'win32') {
954 if (args['_'].length < 1) { response = 'Proper usage: toast "message"'; } else {
@@ -1023,9 +1021,9 @@ function createMeshCore(agent) {
1021 break;
1022 }
1023 case 'info': { // Return information about the agent and agent core module
1026 - response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
1024 + response = 'Current Core: ' + meshCoreObj.value + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + meshCoreObj.caps + '.\r\nServer URL: ' + mesh.ServerUrl + '.';
1025 if (amtLmsState >= 0) { response += '\r\nBuilt-in LMS: ' + ['Disabled', 'Connecting..', 'Connected'][amtLmsState] + '.'; }
1028 - if (osDesc) { response += '\r\nOS: ' + osDesc + '.'; }
1026 + if (meshCoreObj.osdesc) { response += '\r\nOS: ' + meshCoreObj.osdesc + '.'; }
1027 response += '\r\nModules: ' + addedModules.join(', ') + '.';
1028 response += '\r\nServer Connection: ' + mesh.isControlChannelConnected + ', State: ' + meshServerConnectionState + '.';
1029 response += '\r\lastMeInfo: ' + lastMeInfo + '.';
@@ -1048,18 +1046,20 @@ function createMeshCore(agent) {
1046 if (args['_'].length == 0) {
1047 response = 'Proper usage: sendcaps (number)'; // Display correct command usage
1048 } else {
1051 - var flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": parseInt(args['_'][0]) };
1052 - mesh.SendCommand(flags);
1053 - response = JSON.stringify(flags);
1049 + meshCoreObj.caps = parseInt(args['_'][0]);
1050 + mesh.SendCommand(meshCoreObj);
1051 + response = JSON.stringify(meshCoreObj);
1052 }
1053 break;
1054 }
1055 case 'sendosdesc': { // Send OS description
1058 - var os = osDesc;
1059 - if (args['_'].length > 0) { os = args['_'][0]; }
1060 - var flags = { "action": "coreinfo", "value": obj.meshCoreInfo, "osdesc": os };
1061 - mesh.SendCommand(flags);
1062 - response = JSON.stringify(flags);
1056 + if (args['_'].length > 0) {
1057 + meshCoreObj.osdesc = args['_'][0];
1058 + mesh.SendCommand(meshCoreObj);
1059 + response = JSON.stringify(meshCoreObj);
1060 + } else {
1061 + response = 'Proper usage: sendosdesc [os description]'; // Display correct command usage
1062 + }
1063 break;
1064 }
1065 case 'args': { // Displays parsed command arguments
@@ -1362,17 +1362,12 @@ function createMeshCore(agent) {
1362 var oldNodeId = db.Get('OldNodeId');
1363 if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: oldNodeId }); }
1364
1365 - // Update the server with basic info
1366 - var r = { "action": "coreinfo", "value": obj.meshCoreInfo, "caps": obj.meshCoreCapabilities };
1367 - if (osDesc != null) { r.osdesc = osDesc; }
1368 - mesh.SendCommand(r);
1365 + // Update the server with basic info, logged in users and more.
1366 + mesh.SendCommand(meshCoreObj);
1367
1368 // Send SMBios tables if present
1369 if (SMBiosTablesRaw != null) { mesh.SendCommand({ "action": "smbios", "value": SMBiosTablesRaw }); }
1370
1373 - // Update list of logged in users
1374 - if (obj.loggedInUsers != null) { mesh.SendCommand({ "action": "coreinfo", "v": { "users": obj.loggedInUsers } }); }
1375 -
1371 // Update the server on more advanced stuff, like Intel ME and Network Settings
1372 meInfoStr = null;
1373 sendPeriodicServerUpdate();
@@ -1410,8 +1405,12 @@ function createMeshCore(agent) {
1405 if (meinfo.OsHostname) { intelamt.host = meinfo.OsHostname; p = true; }
1406 if (meinfo.UUID) { intelamt.uuid = meinfo.UUID; p = true; }
1407 if (p == true) {
1413 - var meInfoStr = JSON.stringify({ "action": "coreinfo", "value": obj.meshCoreInfo, "intelamt": intelamt });
1414 - if (meInfoStr != lastMeInfo) { mesh.SendCommand(meInfoStr); lastMeInfo = meInfoStr; }
1408 + var meInfoStr = JSON.stringify(intelamt);
1409 + if (meInfoStr != lastMeInfo) {
1410 + meshCoreObj.intelamt = intelamt;
1411 + mesh.SendCommand(meshCoreObj);
1412 + lastMeInfo = meInfoStr;
1413 + }
1414 }
1415 } catch (ex) { }
1416 });
@@ -1492,8 +1491,8 @@ function createMeshCore(agent) {
1491 var un = a[i].Domain ? (a[i].Domain + '\\' + a[i].Username) : (a[i].Username);
1492 if (u.indexOf(un) == -1) { u.push(un); } // Only push users in the list once.
1493 }
1495 - obj.loggedInUsers = u;
1496 - if (mesh.isControlChannelConnected) { mesh.SendCommand({ "action": "coreinfo", "users": u }); }
1494 + meshCoreObj.users = u;
1495 + mesh.SendCommand(meshCoreObj);
1496 });
1497 });
1498 userSession.emit('changed');
meshagent.js
+1 -1
@@ -602,7 +602,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
602 if (mesh == null) return;
603
604 // Get the node and change it if needed
605 - obj.db.Get(obj.dbNodeKey, function (err, nodes) {
605 + obj.db.Get(obj.dbNodeKey, function (err, nodes) { // TODO: THIS IS A BIG RACE CONDITION HERE, WE NEED TO FIX THAT. If this call is made twice at the same time on the same device, data will be missed.
606 if (nodes.length != 1) return;
607 var device = nodes[0];
608 if (device.agent) {
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.2.3-c",
3 + "version": "0.2.3-e",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default.handlebars
+1 -2
@@ -1937,8 +1937,7 @@
1937 // If a device is no longer viewed, disconnect it.
1938 if (multiDesktop[i].xxdelete == true) { multiDesktop[i].Stop(); delete multiDesktop[i]; }
1939 else if (debugmode && multiDesktop[i].m && multiDesktop[i].m.onScreenSizeChange) {
1940 - // Adjust screen size change (JOKO) - This is not good.
1941 - multiDesktop[i].m.onScreenSizeChange();
1940 + mdeskAdjust(multiDesktop[i].m, multiDesktop[i].m.ScreenWidth, multiDesktop[i].m.ScreenHeight, multiDesktop[i].m.CanvasId); // Adjust screen size change
1941 }
1942 }
1943 deskAdjust();