mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	Fixed meshagent connection race on the server.
This commit is contained in:
		
							parent
							
								
									7d38502cbb
								
							
						
					
					
						commit
						d3db0e4ef6
					
				
					 8 changed files with 89 additions and 57 deletions
				
			
		| 
						 | 
					@ -87,22 +87,12 @@ function serviceManager() {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return admin;
 | 
					            return admin;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        this.getProgramFolder = function getProgramFolder() {
 | 
				
			||||||
 | 
					            if ((require('os').arch() == 'x64') && (this.GM.PointerSize == 4)) { return process.env['ProgramFiles(x86)']; } // 64 bit Windows with 32 Bit App
 | 
				
			||||||
 | 
					            return process.env['ProgramFiles']; // All other cases: 32 bit Windows or 64 bit App
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        this.getServiceFolder = function getServiceFolder() {
 | 
					        this.getServiceFolder = function getServiceFolder() {
 | 
				
			||||||
            var destinationFolder = null;
 | 
					            return getProgramFolder() + '\\Open Source\\MeshCmd';
 | 
				
			||||||
            if (require('os').arch() == 'x64') {
 | 
					 | 
				
			||||||
                // 64 bit Windows
 | 
					 | 
				
			||||||
                if (this.GM.PointerSize == 4) {
 | 
					 | 
				
			||||||
                    // 32 Bit App
 | 
					 | 
				
			||||||
                    destinationFolder = process.env['ProgramFiles(x86)'];
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    // 64 bit App
 | 
					 | 
				
			||||||
                    destinationFolder = process.env['ProgramFiles'];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // 32 bit Windows
 | 
					 | 
				
			||||||
                destinationFolder = process.env['ProgramFiles'];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return (destinationFolder + '\\Open Source\\MeshCmd');
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.enumerateService = function () {
 | 
					        this.enumerateService = function () {
 | 
				
			||||||
| 
						 | 
					@ -192,8 +182,10 @@ function serviceManager() {
 | 
				
			||||||
            if (!this.isAdmin()) { throw ('Installing as Service, requires administrator permissions.'); }
 | 
					            if (!this.isAdmin()) { throw ('Installing as Service, requires administrator permissions.'); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Before we start, we need to copy the binary to the right place
 | 
					            // Before we start, we need to copy the binary to the right place
 | 
				
			||||||
            var folder = this.getServiceFolder();
 | 
					            var folder = this.getProgramFolder() + '\\Open Source';
 | 
				
			||||||
            if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
 | 
					            if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "Open Source" folder
 | 
				
			||||||
 | 
					            folder += '\\MeshCmd';
 | 
				
			||||||
 | 
					            if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); } // Create the "MeshCmd" folder
 | 
				
			||||||
            require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
 | 
					            require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
 | 
				
			||||||
            options.servicePath = folder + '\\' + options.name + '.exe';
 | 
					            options.servicePath = folder + '\\' + options.name + '.exe';
 | 
				
			||||||
            console.log('Installing to "' + options.servicePath + '"');
 | 
					            console.log('Installing to "' + options.servicePath + '"');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -484,7 +484,16 @@ module.exports.CertificateOperations = function () {
 | 
				
			||||||
        if (acceleratorCreateCount > 0) {
 | 
					        if (acceleratorCreateCount > 0) {
 | 
				
			||||||
            acceleratorCreateCount--;
 | 
					            acceleratorCreateCount--;
 | 
				
			||||||
            var accelerator = fork(program, [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
 | 
					            var accelerator = fork(program, [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
 | 
				
			||||||
            accelerator.on('message', function (message) { this.func(message); if (pendingAccelerator.length > 0) { accelerator.send(pendingAccelerator.shift()); } else { freeAccelerators.push(this); } });
 | 
					            accelerator.accid = acceleratorCreateCount;
 | 
				
			||||||
 | 
					            accelerator.on('message', function (message) {
 | 
				
			||||||
 | 
					                this.func(this.tag, message);
 | 
				
			||||||
 | 
					                delete this.tag;
 | 
				
			||||||
 | 
					                if (pendingAccelerator.length > 0) {
 | 
				
			||||||
 | 
					                    var x = pendingAccelerator.shift();
 | 
				
			||||||
 | 
					                    if (x.tag) { this.tag = x.tag; delete x.tag; }
 | 
				
			||||||
 | 
					                    accelerator.send(x);
 | 
				
			||||||
 | 
					                } else { freeAccelerators.push(this); }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
            accelerator.send({ action: 'setState', certs: obj.acceleratorCertStore });
 | 
					            accelerator.send({ action: 'setState', certs: obj.acceleratorCertStore });
 | 
				
			||||||
            return accelerator;
 | 
					            return accelerator;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -499,21 +508,22 @@ module.exports.CertificateOperations = function () {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Perform any RSA signature, just pass in the private key and data.
 | 
					    // Perform any RSA signature, just pass in the private key and data.
 | 
				
			||||||
    obj.acceleratorPerformSignature = function (privatekey, data, func) {
 | 
					    obj.acceleratorPerformSignature = function (privatekey, data, tag, func) {
 | 
				
			||||||
        if (acceleratorTotalCount <= 1) {
 | 
					        if (acceleratorTotalCount <= 1) {
 | 
				
			||||||
            // No accelerators available
 | 
					            // No accelerators available
 | 
				
			||||||
            if (typeof privatekey == 'number') { privatekey = obj.acceleratorCertStore[privatekey].key; }
 | 
					            if (typeof privatekey == 'number') { privatekey = obj.acceleratorCertStore[privatekey].key; }
 | 
				
			||||||
            const sign = obj.crypto.createSign('SHA384');
 | 
					            const sign = obj.crypto.createSign('SHA384');
 | 
				
			||||||
            sign.end(new Buffer(data, 'binary'));
 | 
					            sign.end(new Buffer(data, 'binary'));
 | 
				
			||||||
            func(sign.sign(privatekey).toString('binary'));
 | 
					            func(tag, sign.sign(privatekey).toString('binary'));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            var acc = obj.getAccelerator();
 | 
					            var acc = obj.getAccelerator();
 | 
				
			||||||
            if (acc == null) {
 | 
					            if (acc == null) {
 | 
				
			||||||
                // Add to pending accelerator workload
 | 
					                // Add to pending accelerator workload
 | 
				
			||||||
                pendingAccelerator.push({ action: 'sign', key: privatekey, data: data });
 | 
					                pendingAccelerator.push({ action: 'sign', key: privatekey, data: data, tag: tag });
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Send to accelerator now
 | 
					                // Send to accelerator now
 | 
				
			||||||
                acc.func = func;
 | 
					                acc.func = func;
 | 
				
			||||||
 | 
					                acc.tag = tag;
 | 
				
			||||||
                acc.send({ action: 'sign', key: privatekey, data: data });
 | 
					                acc.send({ action: 'sign', key: privatekey, data: data });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								meshagent.js
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								meshagent.js
									
										
									
									
									
								
							| 
						 | 
					@ -6,6 +6,8 @@
 | 
				
			||||||
* @version v0.0.1
 | 
					* @version v0.0.1
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var AgentConnectCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Construct a MeshAgent object, called upon connection
 | 
					// Construct a MeshAgent object, called upon connection
 | 
				
			||||||
module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
					module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
    var obj = {};
 | 
					    var obj = {};
 | 
				
			||||||
| 
						 | 
					@ -30,6 +32,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
    const agentUpdateBlockSize = 65520;
 | 
					    const agentUpdateBlockSize = 65520;
 | 
				
			||||||
    obj.remoteaddr = obj.ws._socket.remoteAddress;
 | 
					    obj.remoteaddr = obj.ws._socket.remoteAddress;
 | 
				
			||||||
    obj.useSHA386 = false;
 | 
					    obj.useSHA386 = false;
 | 
				
			||||||
 | 
					    obj.agentConnectCount = ++AgentConnectCount;
 | 
				
			||||||
    if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }
 | 
					    if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }
 | 
				
			||||||
    ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive, 4 minutes
 | 
					    ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive, 4 minutes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,6 +68,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
                if ((state.connectivity & 2) != 0) { obj.parent.parent.mpsserver.close(obj.parent.parent.mpsserver.ciraConnections[obj.dbNodeKey]); } // Disconnect CIRA connection
 | 
					                if ((state.connectivity & 2) != 0) { obj.parent.parent.mpsserver.close(obj.parent.parent.mpsserver.ciraConnections[obj.dbNodeKey]); } // Disconnect CIRA connection
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        delete obj.nodeid;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // When data is received from the mesh agent web socket
 | 
					    // When data is received from the mesh agent web socket
 | 
				
			||||||
| 
						 | 
					@ -183,15 +187,15 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
                obj.agentnonce = msg.substring(50);
 | 
					                obj.agentnonce = msg.substring(50);
 | 
				
			||||||
                if (obj.useSwarmCert == true) {
 | 
					                if (obj.useSwarmCert == true) {
 | 
				
			||||||
                    // Perform the hash signature using older swarm server certificate
 | 
					                    // Perform the hash signature using older swarm server certificate
 | 
				
			||||||
                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, function (signature) {
 | 
					                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
 | 
				
			||||||
                        // Send back our certificate + signature
 | 
					                        // Send back our certificate + signature
 | 
				
			||||||
                        obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.parent.swarmCertificateAsn1.length) + obj.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
					                        obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.parent.swarmCertificateAsn1.length) + obj2.parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    // Perform the hash signature using the server agent certificate
 | 
					                    // Perform the hash signature using the server agent certificate
 | 
				
			||||||
                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
 | 
					                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
 | 
				
			||||||
                        // Send back our certificate + signature
 | 
					                        // Send back our certificate + signature
 | 
				
			||||||
                        obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.parent.agentCertificateAsn1.length) + obj.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
					                        obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.parent.agentCertificateAsn1.length) + obj2.parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,7 +263,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Once we get all the information about an agent, run this to hook everything up to the server
 | 
					    // Once we get all the information about an agent, run this to hook everything up to the server
 | 
				
			||||||
    function completeAgentConnection() {
 | 
					    function completeAgentConnection() {
 | 
				
			||||||
        if (obj.authenticated =! 1 || obj.meshid == null) return;
 | 
					        if (obj.authenticated = !1 || obj.meshid == null || obj.pendingCompleteAgentConnection) return;
 | 
				
			||||||
 | 
					        obj.pendingCompleteAgentConnection = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check that the mesh exists
 | 
					        // Check that the mesh exists
 | 
				
			||||||
        obj.db.Get(obj.dbMeshKey, function (err, meshes) {
 | 
					        obj.db.Get(obj.dbMeshKey, function (err, meshes) {
 | 
				
			||||||
            if (meshes.length == 0) { console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddr + ', ' + obj.dbMeshKey + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
 | 
					            if (meshes.length == 0) { console.log('Agent connected with invalid domain/mesh, holding connection (' + obj.remoteaddr + ', ' + obj.dbMeshKey + ').'); return; } // If we disconnect, the agnet will just reconnect. We need to log this or tell agent to connect in a few hours.
 | 
				
			||||||
| 
						 | 
					@ -327,6 +333,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // We are done, ready to communicate with this agent
 | 
					                // We are done, ready to communicate with this agent
 | 
				
			||||||
 | 
					                delete obj.pendingCompleteAgentConnection;
 | 
				
			||||||
                obj.authenticated = 2;
 | 
					                obj.authenticated = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Command 4, inform mesh agent that it's authenticated.
 | 
					                // Command 4, inform mesh agent that it's authenticated.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,9 +94,9 @@ module.exports.CreateMultiServer = function (parent, args) {
 | 
				
			||||||
                            obj.servernonce = msg.substring(50);
 | 
					                            obj.servernonce = msg.substring(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            // Perform the hash signature using the server agent certificate
 | 
					                            // Perform the hash signature using the server agent certificate
 | 
				
			||||||
                            obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
 | 
					                            obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) {
 | 
				
			||||||
                                // Send back our certificate + signature
 | 
					                                // Send back our certificate + signature
 | 
				
			||||||
                                obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
					                                obj2.ws.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
				
			||||||
                            });
 | 
					                            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
| 
						 | 
					@ -257,9 +257,9 @@ module.exports.CreateMultiServer = function (parent, args) {
 | 
				
			||||||
                    obj.peernonce = msg.substring(50);
 | 
					                    obj.peernonce = msg.substring(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Perform the hash signature using the server agent certificate
 | 
					                    // Perform the hash signature using the server agent certificate
 | 
				
			||||||
                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, function (signature) {
 | 
					                    obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (signature) {
 | 
				
			||||||
                        // Send back our certificate + signature
 | 
					                        // Send back our certificate + signature
 | 
				
			||||||
                        obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
					                        obj2.send(obj2.common.ShortToStr(2) + obj.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Check the peer server signature if we can
 | 
					                    // Check the peer server signature if we can
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "name": "meshcentral",
 | 
					  "name": "meshcentral",
 | 
				
			||||||
  "version": "0.1.9-i",
 | 
					  "version": "0.1.9-j",
 | 
				
			||||||
  "keywords": [
 | 
					  "keywords": [
 | 
				
			||||||
    "Remote Management",
 | 
					    "Remote Management",
 | 
				
			||||||
    "Intel AMT",
 | 
					    "Intel AMT",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1177,6 +1177,10 @@
 | 
				
			||||||
        // MY DEVICES
 | 
					        // MY DEVICES
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
 | 
				
			||||||
 | 
					        var updateDevicesTimer = null;
 | 
				
			||||||
 | 
					        function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var sort = 0;
 | 
					        var sort = 0;
 | 
				
			||||||
        var deviceHeaderId = 0;
 | 
					        var deviceHeaderId = 0;
 | 
				
			||||||
        var deviceHeaderCount;
 | 
					        var deviceHeaderCount;
 | 
				
			||||||
| 
						 | 
					@ -1185,7 +1189,7 @@
 | 
				
			||||||
        var deviceHeaderTotal = 0;
 | 
					        var deviceHeaderTotal = 0;
 | 
				
			||||||
        var deviceHeaders = {};
 | 
					        var deviceHeaders = {};
 | 
				
			||||||
        var deviceHeadersTitles = {};
 | 
					        var deviceHeadersTitles = {};
 | 
				
			||||||
        function updateDevices() {
 | 
					        function updateDevicesEx() {
 | 
				
			||||||
            var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
 | 
					            var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 3 wide, list view or desktop view
 | 
					            // 3 wide, list view or desktop view
 | 
				
			||||||
| 
						 | 
					@ -1196,6 +1200,11 @@
 | 
				
			||||||
            deviceHeadersTitles = {};
 | 
					            deviceHeadersTitles = {};
 | 
				
			||||||
            var current;
 | 
					            var current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Perform node sort
 | 
				
			||||||
 | 
					            if (sort == 0) { nodes.sort(meshSort); }
 | 
				
			||||||
 | 
					            else if (sort == 1) { nodes.sort(powerSort); }
 | 
				
			||||||
 | 
					            else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Go thru the list of nodes and display them
 | 
					            // Go thru the list of nodes and display them
 | 
				
			||||||
            for (var i in nodes) {
 | 
					            for (var i in nodes) {
 | 
				
			||||||
                if (nodes[i].v == false) continue;
 | 
					                if (nodes[i].v == false) continue;
 | 
				
			||||||
| 
						 | 
					@ -1324,10 +1333,7 @@
 | 
				
			||||||
        function onSortSelectChange(skipsave) {
 | 
					        function onSortSelectChange(skipsave) {
 | 
				
			||||||
            sort = document.getElementById("sortselect").selectedIndex;
 | 
					            sort = document.getElementById("sortselect").selectedIndex;
 | 
				
			||||||
            if (!skipsave) { putstore("sort", sort); }
 | 
					            if (!skipsave) { putstore("sort", sort); }
 | 
				
			||||||
            if (sort == 0) { nodes.sort(meshSort); }
 | 
					            updateDevicesEx();
 | 
				
			||||||
            if (sort == 1) { nodes.sort(powerSort); }
 | 
					 | 
				
			||||||
            if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
 | 
					 | 
				
			||||||
            updateDevices();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function deviceHeaderSet() {
 | 
					        function deviceHeaderSet() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -842,7 +842,6 @@
 | 
				
			||||||
            // Display the page devices
 | 
					            // Display the page devices
 | 
				
			||||||
            onSortSelectChange();
 | 
					            onSortSelectChange();
 | 
				
			||||||
            onSearchInputChanged();
 | 
					            onSearchInputChanged();
 | 
				
			||||||
            updateDevices();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Setup upload drag & drop
 | 
					            // Setup upload drag & drop
 | 
				
			||||||
            Q('p5filetable').addEventListener("drop", p5fileDragDrop, false);
 | 
					            Q('p5filetable').addEventListener("drop", p5fileDragDrop, false);
 | 
				
			||||||
| 
						 | 
					@ -1494,11 +1493,16 @@
 | 
				
			||||||
            if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
 | 
					            if (Q('viewselect').value == 3) { if ((e.keyCode === 8 && mapSearchFocus == 0) || e.keyCode === 27) { return haltEvent(e); } }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Since the update device call can be quite frequent, we can moderate it and only call it at most 5 times a second.
 | 
				
			||||||
 | 
					        var updateDevicesTimer = null;
 | 
				
			||||||
 | 
					        function updateDevices() { if (updateDevicesTimer != null) return; updateDevicesTimer = setTimeout(updateDevicesEx, 200); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var deviceHeaderId = 0;
 | 
					        var deviceHeaderId = 0;
 | 
				
			||||||
        var deviceHeaderCount;
 | 
					        var deviceHeaderCount;
 | 
				
			||||||
        var deviceHeaders = {};
 | 
					        var deviceHeaders = {};
 | 
				
			||||||
        var oldviewmode = 0;
 | 
					        var oldviewmode = 0;
 | 
				
			||||||
        function updateDevices() {
 | 
					        function updateDevicesEx() {
 | 
				
			||||||
 | 
					            if (updateDevicesTimer != null) { clearTimeout(updateDevicesTimer); updateDevicesTimer = null; }
 | 
				
			||||||
            var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
 | 
					            var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
 | 
				
			||||||
            QV('xdevices', view < 4);
 | 
					            QV('xdevices', view < 4);
 | 
				
			||||||
            QV('xdevicesmap', view == 4);
 | 
					            QV('xdevicesmap', view == 4);
 | 
				
			||||||
| 
						 | 
					@ -1522,9 +1526,14 @@
 | 
				
			||||||
                deviceHeadersTitles = {};
 | 
					                deviceHeadersTitles = {};
 | 
				
			||||||
                var kvmDivs = [];
 | 
					                var kvmDivs = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Perform node sort
 | 
				
			||||||
 | 
					                if (sort == 0) { nodes.sort(meshSort); }
 | 
				
			||||||
 | 
					                else if (sort == 1) { nodes.sort(powerSort); }
 | 
				
			||||||
 | 
					                else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Save the list of currently checked nodeid's
 | 
					                // Save the list of currently checked nodeid's
 | 
				
			||||||
                var checkedNodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
					                var checkedNodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
				
			||||||
                for (var i in elements) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
 | 
					                for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
 | 
				
			||||||
                if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
 | 
					                if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
 | 
				
			||||||
                else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
 | 
					                else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1551,11 +1560,12 @@
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } else if (sort == 1) {
 | 
					                    } else if (sort == 1) {
 | 
				
			||||||
                        // Power header
 | 
					                        // Power header
 | 
				
			||||||
                        if (nodes[i].pwr !== current) {
 | 
					                        var pwr = nodes[i].pwr?nodes[i].pwr:0;
 | 
				
			||||||
 | 
					                        if (pwr !== current) {
 | 
				
			||||||
                            deviceHeaderSet();
 | 
					                            deviceHeaderSet();
 | 
				
			||||||
                            if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
 | 
					                            if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
 | 
				
			||||||
                            r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
 | 
					                            r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
 | 
				
			||||||
                            current = nodes[i].pwr;
 | 
					                            current = pwr;
 | 
				
			||||||
                            c = 0;
 | 
					                            c = 0;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } else if (sort == 2) {
 | 
					                    } else if (sort == 2) {
 | 
				
			||||||
| 
						 | 
					@ -1670,7 +1680,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Re-check nodeid's
 | 
					                // Re-check nodeid's
 | 
				
			||||||
                var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
					                var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
				
			||||||
                for (var i in elements) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
 | 
					                for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
 | 
					                for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
 | 
				
			||||||
                for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
 | 
					                for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
 | 
				
			||||||
| 
						 | 
					@ -1862,7 +1872,7 @@
 | 
				
			||||||
        // Called when OK is pressed on the Intel AMT scanning box
 | 
					        // Called when OK is pressed on the Intel AMT scanning box
 | 
				
			||||||
        function addAmtScanToMeshEx(button, meshid) {
 | 
					        function addAmtScanToMeshEx(button, meshid) {
 | 
				
			||||||
            var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
 | 
					            var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
 | 
				
			||||||
            for (var i in elements) {
 | 
					            for (var i=0;i<elements.length;i++) {
 | 
				
			||||||
                if (elements[i].checked) {
 | 
					                if (elements[i].checked) {
 | 
				
			||||||
                    var ipaddr = elements[i].getAttribute('tag');
 | 
					                    var ipaddr = elements[i].getAttribute('tag');
 | 
				
			||||||
                    var amtinfo = amtScanResults[ipaddr];
 | 
					                    var amtinfo = amtScanResults[ipaddr];
 | 
				
			||||||
| 
						 | 
					@ -1882,7 +1892,7 @@
 | 
				
			||||||
        // Called when a scanned computer is checked or unchecked.
 | 
					        // Called when a scanned computer is checked or unchecked.
 | 
				
			||||||
        function addAmtScanToMeshCheckbox() {
 | 
					        function addAmtScanToMeshCheckbox() {
 | 
				
			||||||
            var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
 | 
					            var elements = document.getElementsByClassName("DevScanCheckbox"), checkcount = 0;
 | 
				
			||||||
            for (var i in elements) { if (elements[i].checked) checkcount++; }
 | 
					            for (var i=0;i<elements.length;i++) { if (elements[i].checked) checkcount++; }
 | 
				
			||||||
            QE('idx_dlgOkButton', checkcount > 0);
 | 
					            QE('idx_dlgOkButton', checkcount > 0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2063,14 +2073,14 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function selectallButtonFunction() {
 | 
					        function selectallButtonFunction() {
 | 
				
			||||||
            var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
					            var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
				
			||||||
            for (var i in elements) { if (elements[i].checked) checkcount++; }
 | 
					            for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
 | 
				
			||||||
            for (var i in elements) { elements[i].checked = (checkcount == 0); }
 | 
					            for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
 | 
				
			||||||
            p1updateInfo();
 | 
					            p1updateInfo();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function p1updateInfo() {
 | 
					        function p1updateInfo() {
 | 
				
			||||||
            var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
					            var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
				
			||||||
            for (var i in elements) { if (elements[i].checked) checkcount++; }
 | 
					            for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
 | 
				
			||||||
            if (checkcount > 0) {
 | 
					            if (checkcount > 0) {
 | 
				
			||||||
                QE('GroupActionButton', true);
 | 
					                QE('GroupActionButton', true);
 | 
				
			||||||
                Q('SelectAllButton').value = 'Select None';
 | 
					                Q('SelectAllButton').value = 'Select None';
 | 
				
			||||||
| 
						 | 
					@ -2093,7 +2103,7 @@
 | 
				
			||||||
        // Get the list of checked devices, removes any duplicates.
 | 
					        // Get the list of checked devices, removes any duplicates.
 | 
				
			||||||
        function getCheckedDevices() {
 | 
					        function getCheckedDevices() {
 | 
				
			||||||
            var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
					            var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
 | 
				
			||||||
            for (var i in elements) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
 | 
					            for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
 | 
				
			||||||
            return nodeids;
 | 
					            return nodeids;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2120,14 +2130,11 @@
 | 
				
			||||||
        function onSortSelectChange(skipsave) {
 | 
					        function onSortSelectChange(skipsave) {
 | 
				
			||||||
            sort = document.getElementById("sortselect").selectedIndex;
 | 
					            sort = document.getElementById("sortselect").selectedIndex;
 | 
				
			||||||
            if (!skipsave) { putstore("sort", sort); }
 | 
					            if (!skipsave) { putstore("sort", sort); }
 | 
				
			||||||
            if (sort == 0) { nodes.sort(meshSort); }
 | 
					            updateDevicesEx();
 | 
				
			||||||
            if (sort == 1) { nodes.sort(powerSort); }
 | 
					 | 
				
			||||||
            if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
 | 
					 | 
				
			||||||
            updateDevices();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
 | 
					        function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
 | 
				
			||||||
        function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } if (ap > bp) return 1; if (ap < bp) return -1; return 0; }
 | 
					        function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap > bp) return -1; if (ap < bp) return 1; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
 | 
				
			||||||
        function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
 | 
					        function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
 | 
				
			||||||
        function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
 | 
					        function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
 | 
				
			||||||
        function onSearchFocus(x) { searchFocus = x; }
 | 
					        function onSearchFocus(x) { searchFocus = x; }
 | 
				
			||||||
| 
						 | 
					@ -2200,8 +2207,8 @@
 | 
				
			||||||
        function cmmeshaction(action) {
 | 
					        function cmmeshaction(action) {
 | 
				
			||||||
            var meshid = contextelement.attributes.onclick.value.substring(32, (32 + 69));
 | 
					            var meshid = contextelement.attributes.onclick.value.substring(32, (32 + 69));
 | 
				
			||||||
            var elements = document.getElementsByClassName("DeviceCheckbox");
 | 
					            var elements = document.getElementsByClassName("DeviceCheckbox");
 | 
				
			||||||
            if (action == 1) { for (var i in elements) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = true; } } }
 | 
					            if (action == 1) { for (var i=0;i<elements.length;i++) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = true; } } }
 | 
				
			||||||
            if (action == 2) { for (var i in elements) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = false; } } }
 | 
					            if (action == 2) { for (var i=0;i<elements.length;i++) { if (elements[i].attributes && elements[i].attributes.class.value.substring(0, 69) == meshid) { elements[i].checked = false; } } }
 | 
				
			||||||
            //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
 | 
					            //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
 | 
				
			||||||
            p1updateInfo();
 | 
					            p1updateInfo();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -5802,7 +5809,7 @@
 | 
				
			||||||
            QV('UserSubMenuSpan', x >= 30 && x < 40);
 | 
					            QV('UserSubMenuSpan', x >= 30 && x < 40);
 | 
				
			||||||
            QS('UserGeneral').backgroundColor = ((x == 30) ? "#003366" : "#808080");
 | 
					            QS('UserGeneral').backgroundColor = ((x == 30) ? "#003366" : "#808080");
 | 
				
			||||||
            QS('UserEvents').backgroundColor = ((x == 31) ? "#003366" : "#808080");
 | 
					            QS('UserEvents').backgroundColor = ((x == 31) ? "#003366" : "#808080");
 | 
				
			||||||
            if (x == 1) updateDevices();
 | 
					            if (x == 1) updateDevicesEx();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Generic methods
 | 
					        // Generic methods
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								webserver.js
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								webserver.js
									
										
									
									
									
								
							| 
						 | 
					@ -71,6 +71,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
 | 
				
			||||||
    obj.userAllowedIp = args.userallowedip;  // List of allowed IP addresses for users
 | 
					    obj.userAllowedIp = args.userallowedip;  // List of allowed IP addresses for users
 | 
				
			||||||
    obj.tlsSniCredentials;
 | 
					    obj.tlsSniCredentials;
 | 
				
			||||||
    obj.dnsDomains = {};
 | 
					    obj.dnsDomains = {};
 | 
				
			||||||
 | 
					    //obj.agentConnCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Mesh Rights
 | 
					    // Mesh Rights
 | 
				
			||||||
    const MESHRIGHT_EDITMESH = 1;
 | 
					    const MESHRIGHT_EDITMESH = 1;
 | 
				
			||||||
| 
						 | 
					@ -1695,7 +1696,16 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
 | 
				
			||||||
        obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { try { obj.meshRelayHandler.CreateMeshRelay(obj, ws, req, getDomain(req)); } catch (e) { console.log(e); } });
 | 
					        obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { try { obj.meshRelayHandler.CreateMeshRelay(obj, ws, req, getDomain(req)); } catch (e) { console.log(e); } });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Receive mesh agent connections
 | 
					        // Receive mesh agent connections
 | 
				
			||||||
        obj.app.ws(url + 'agent.ashx', function (ws, req) { try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, getDomain(req)); } catch (e) { console.log(e); } });
 | 
					        obj.app.ws(url + 'agent.ashx', function (ws, req) {
 | 
				
			||||||
 | 
					            //console.log(++obj.agentConnCount);
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					            var ip, port, type;
 | 
				
			||||||
 | 
					            if (req.connection) { ip = req.connection.remoteAddress; port = req.connection.remotePort; type = 1; } // HTTP(S) request
 | 
				
			||||||
 | 
					            else if (req._socket) { ip = req._socket.remoteAddress; port = req._socket.remotePort; type = 2; } // WebSocket request
 | 
				
			||||||
 | 
					            console.log('AgentConnect', ip, port, type);
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, getDomain(req)); } catch (e) { console.log(e); }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        obj.app.get(url + 'stop', function (req, res) { res.send('Stopping Server, <a href="' + url + '">click here to login</a>.'); setTimeout(function () { parent.Stop(); }, 500); });
 | 
					        obj.app.get(url + 'stop', function (req, res) { res.send('Stopping Server, <a href="' + url + '">click here to login</a>.'); setTimeout(function () { parent.Stop(); }, 500); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue