From 768da89ff0a2e406b90599c8a4fafe617887c7d5 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 20 Feb 2019 15:26:27 -0800 Subject: [PATCH] DB performance fixes. --- db.js | 4 +- meshagent.js | 5 +- mpsserver.js | 123 ++++++++++++------------- package.json | 2 +- public/scripts/agent-redir-ws-0.1.0.js | 2 +- views/default-min.handlebars | 2 +- views/default-mobile-min.handlebars | 2 +- views/default.handlebars | 10 +- 8 files changed, 77 insertions(+), 73 deletions(-) diff --git a/db.js b/db.js index 9291fe23..fc5a225c 100644 --- a/db.js +++ b/db.js @@ -71,10 +71,12 @@ module.exports.CreateDB = function (parent) { // Check if we need to reset indexes var indexesByName = {}, indexCount = 0; for (var i in indexes) { indexesByName[indexes[i].name] = indexes[i]; indexCount++; } - if ((indexCount != 3) || (indexesByName['IdsAndTime1'] == null) || (indexesByName['ExpireTime1'] == null)) { + if ((indexCount != 5) || (indexesByName['Username1'] == null) || (indexesByName['DomainNodeTime1'] == null) || (indexesByName['IdsAndTime1'] == null) || (indexesByName['ExpireTime1'] == null)) { // Reset all indexes console.log('Resetting events indexes...'); obj.eventsfile.dropIndexes(function (err) { + obj.eventsfile.createIndex({ username: 1 }, { sparse: 1, name: 'Username1' }); + obj.eventsfile.createIndex({ domain: 1, nodeid: 1, time: -1 }, { sparse: 1, name: 'DomainNodeTime1' }); obj.eventsfile.createIndex({ ids: 1, time: -1 }, { sparse: 1, name: 'IdsAndTime1' }); obj.eventsfile.createIndex({ "time": 1 }, { expireAfterSeconds: expireEventsSeconds, name: 'ExpireTime1' }); }); diff --git a/meshagent.js b/meshagent.js index 65a387c8..416bbee5 100644 --- a/meshagent.js +++ b/meshagent.js @@ -1017,8 +1017,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if ((command.intelamt.uuid != null) && (device.intelamt.uuid != command.intelamt.uuid)) { changes.push('AMT uuid'); device.intelamt.uuid = command.intelamt.uuid; change = 1; log = 1; } } if ((command.users != null) && (device.users != command.users)) { device.users = command.users; change = 1; } // Don't save this to the db. - if (mesh.mtype == 2) { - if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; log = 1; changes.push('host'); } + if ((mesh.mtype == 2) && (!obj.args.wanonly)) { + // In WAN mode, the hostname of a computer is not important. Don't log hostname changes. + if (device.host != obj.remoteaddr) { device.host = obj.remoteaddr; change = 1; changes.push('host'); } // TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match. } diff --git a/mpsserver.js b/mpsserver.js index f209040b..a56f785f 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -246,80 +246,77 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { // Check the CIRA username, which should be the start of the MeshID. if (usernameLen != 16) { Debug(1, 'MPS:Username length not 16', username, password); SendUserAuthFail(socket); return -1; } - var meshIdStart = '/' + username; - obj.db.GetAllType('mesh', function (err, docs) { - var mesh = null; - for (var i in docs) { if (docs[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = docs[i]; break; } } - if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password); SendUserAuthFail(socket); return -1; } + var meshIdStart = '/' + username, mesh = null; + if (obj.parent.webserver.meshes) { for (var i in obj.parent.webserver.meshes) { if (obj.parent.webserver.meshes[i]._id.replace(/\@/g, 'X').replace(/\$/g, 'X').indexOf(meshIdStart) > 0) { mesh = obj.parent.webserver.meshes[i]; break; } } } + if (mesh == null) { Debug(1, 'MPS:Mesh not found', username, password); SendUserAuthFail(socket); return -1; } - // If this is a agent-less mesh, use the device guid 3 times as ID. - if (mesh.mtype == 1) { - // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID - var systemid = socket.tag.SystemId.split('-').join(''); - var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); - socket.tag.name = ''; - socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded - socket.tag.meshid = mesh._id; - socket.tag.connectTime = Date.now(); + // If this is a agent-less mesh, use the device guid 3 times as ID. + if (mesh.mtype == 1) { + // Intel AMT GUID (socket.tag.SystemId) will be used as NodeID + var systemid = socket.tag.SystemId.split('-').join(''); + var nodeid = Buffer.from(systemid + systemid + systemid, 'hex').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'); + socket.tag.name = ''; + socket.tag.nodeid = 'node/' + mesh.domain + '/' + nodeid; // Turn 16bit systemid guid into 48bit nodeid that is base64 encoded + socket.tag.meshid = mesh._id; + socket.tag.connectTime = Date.now(); - obj.db.Get(socket.tag.nodeid, function (err, nodes) { - if (nodes.length == 0) { - if (mesh.mtype == 1) { - // Node is not in the database, add it. Credentials will be empty until added by the user. - var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; - obj.db.Set(device); + obj.db.Get(socket.tag.nodeid, function (err, nodes) { + if (nodes.length == 0) { + if (mesh.mtype == 1) { + // Node is not in the database, add it. Credentials will be empty until added by the user. + var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } }; + obj.db.Set(device); - // Event the new node - var device2 = common.Clone(device); - if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. - var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; - obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); - } else { - // New CIRA connection for unknown node, disconnect. - console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid); - socket.end(); - return; - } + // Event the new node + var device2 = common.Clone(device); + if (device2.intelamt.pass != undefined) delete device2.intelamt.pass; // Remove the Intel AMT password before eventing this. + var change = 'CIRA added device ' + socket.tag.name + ' to mesh ' + mesh.name; + obj.parent.DispatchEvent(['*', socket.tag.meshid], obj, { etype: 'node', action: 'addnode', node: device2, msg: change, domain: mesh.domain }); } else { - // Node is already present - var node = nodes[0]; - if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; } - } - - // Add the connection to the MPS connection list - obj.ciraConnections[socket.tag.nodeid] = socket; - obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. - SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection - }); - } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID - // Intel AMT GUID (socket.tag.SystemId) will be used to search the node - obj.db.getAmtUuidNode(mesh._id, socket.tag.SystemId, function (err, nodes) { - if (nodes.length == 0) { // New CIRA connection for unknown node, disconnect. - console.log('CIRA connection for unknown node. meshid: ' + mesh._id + ', uuid: ' + systemid); + console.log('CIRA connection for unknown node with incorrect mesh type. meshid: ' + socket.tag.meshid); socket.end(); return; } - - // Node is present + } else { + // Node is already present var node = nodes[0]; if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; } - socket.tag.nodeid = node._id; - socket.tag.meshid = mesh._id; - socket.tag.connectTime = Date.now(); + } - // Add the connection to the MPS connection list - obj.ciraConnections[socket.tag.nodeid] = socket; - obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. - SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection - }); - } else { // Unknown mesh type - // New CIRA connection for unknown node, disconnect. - console.log('CIRA connection to a unknown mesh type. meshid: ' + socket.tag.meshid); - socket.end(); - return; - } - }); + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection + }); + } else if (mesh.mtype == 2) { // If this is a agent mesh, search the mesh for this device UUID + // Intel AMT GUID (socket.tag.SystemId) will be used to search the node + obj.db.getAmtUuidNode(mesh._id, socket.tag.SystemId, function (err, nodes) { // TODO: May need to optimize this request with indexes + if (nodes.length == 0) { + // New CIRA connection for unknown node, disconnect. + console.log('CIRA connection for unknown node. meshid: ' + mesh._id + ', uuid: ' + systemid); + socket.end(); + return; + } + + // Node is present + var node = nodes[0]; + if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; } + socket.tag.nodeid = node._id; + socket.tag.meshid = mesh._id; + socket.tag.connectTime = Date.now(); + + // Add the connection to the MPS connection list + obj.ciraConnections[socket.tag.nodeid] = socket; + obj.parent.SetConnectivityState(socket.tag.meshid, socket.tag.nodeid, socket.tag.connectTime, 2, 7); // TODO: Right now report power state as "present" (7) until we can poll. + SendUserAuthSuccess(socket); // Notify the auth success on the CIRA connection + }); + } else { // Unknown mesh type + // New CIRA connection for unknown node, disconnect. + console.log('CIRA connection to a unknown mesh type. meshid: ' + socket.tag.meshid); + socket.end(); + return; + } return 18 + usernameLen + serviceNameLen + methodNameLen + passwordLen; } case APFProtocol.SERVICE_REQUEST: { diff --git a/package.json b/package.json index f41a2757..d524f42f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.2.8-y", + "version": "0.2.8-z", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/scripts/agent-redir-ws-0.1.0.js b/public/scripts/agent-redir-ws-0.1.0.js index 70a274f6..26ca551f 100644 --- a/public/scripts/agent-redir-ws-0.1.0.js +++ b/public/scripts/agent-redir-ws-0.1.0.js @@ -39,7 +39,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au obj.socket.onopen = obj.xxOnSocketConnected; obj.socket.onmessage = obj.xxOnMessage; //obj.socket.onmessage = function (e) { console.log('Websocket data', e.data); obj.xxOnMessage(e); } - obj.socket.onerror = function (e) { console.error(e); } + obj.socket.onerror = function (e) { /* console.error(e); */ } obj.socket.onclose = obj.xxOnSocketClosed; obj.xxStateChange(1); //obj.meshserver.send({ action: 'msg', type: 'tunnel', nodeid: obj.nodeid, value: url2 }); diff --git a/views/default-min.handlebars b/views/default-min.handlebars index 176f6fe6..ebe8e535 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default-mobile-min.handlebars b/views/default-mobile-min.handlebars index e13d5952..1477de47 100644 --- a/views/default-mobile-min.handlebars +++ b/views/default-mobile-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}
\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}
\ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index 8c9a96ff..43e96489 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1803,7 +1803,7 @@ } case 'stopped': { // Server is stopping. // Disconnect - console.log(message.msg); + //console.log(message.msg); break; } default: @@ -3391,6 +3391,10 @@ var powerTimeline = null; function getCurrentNode() { return currentNode; }; function gotoDevice(nodeid, panel, refresh, event) { + + // Check if we are allowed to create a new device group + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "New Device Group", 1, null, "Unable to create a new device group until a email address is verified. This is required for password recovery. Go to the \"My Account\" tab to change and verify an email address."); return; } + if (event && (event.shiftKey == true)) { // Open the device in a different tab window.open(window.location.origin + '?node=' + nodeid.split('/')[2] + '&viewmode=10&hide=16', 'meshcentral:' + nodeid); @@ -4266,7 +4270,7 @@ } function applyDesktopSettings() { - var r = '', ops = (features & 512)?[90,70,50,40,30,20,10,5,1]:[50,40,30,20,10,5,1]; + var r = '', ops = (features & 512)?[90,80,70,60,50,40,30,20,10,5,1]:[60,50,40,30,20,10,5,1]; for (var i in ops) { r += ''; } QH('d7bitmapquality', r); d7desktopmode.value = desktopsettings.encoding; @@ -5580,7 +5584,7 @@ if (xxdialogMode) return; // Check if we are allowed to create a new device group - if ((userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "New Device Group", 1, null, "Unable to create a new device group until the email address is verified. Go to the \"My Account\" tab to change and verify an email address."); return; } + if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "New Device Group", 1, null, "Unable to create a new device group until a email address is verified. This is required for password recovery. Go to the \"My Account\" tab to change and verify an email address."); return; } // We are allowed, let's prompt to information var x = "Create a new device group using the options below.

";