mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	Added support for dynamic relayid change for WebPowerSwitch and Raritan.
This commit is contained in:
		
							parent
							
								
									4e2b334f02
								
							
						
					
					
						commit
						3a1d3433cf
					
				
					 3 changed files with 47 additions and 21 deletions
				
			
		
							
								
								
									
										64
									
								
								meshipkvm.js
									
										
									
									
									
								
							
							
						
						
									
										64
									
								
								meshipkvm.js
									
										
									
									
									
								
							| 
						 | 
					@ -37,7 +37,7 @@ function CreateIPKVMManager(parent) {
 | 
				
			||||||
    const MESHRIGHT_ADMIN = 0xFFFFFFFF;
 | 
					    const MESHRIGHT_ADMIN = 0xFFFFFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Subscribe for mesh creation events
 | 
					    // Subscribe for mesh creation events
 | 
				
			||||||
    parent.AddEventDispatch(['server-createmesh', 'server-deletemesh', 'devport-operation'], obj);
 | 
					    parent.AddEventDispatch(['server-createmesh', 'server-deletemesh', 'server-editmesh', 'devport-operation'], obj);
 | 
				
			||||||
    obj.HandleEvent = function (source, event, ids, id) {
 | 
					    obj.HandleEvent = function (source, event, ids, id) {
 | 
				
			||||||
        if ((event == null) || (event.mtype != 4)) return;
 | 
					        if ((event == null) || (event.mtype != 4)) return;
 | 
				
			||||||
        if (event.action == 'createmesh') {
 | 
					        if (event.action == 'createmesh') {
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,9 @@ function CreateIPKVMManager(parent) {
 | 
				
			||||||
        } else if (event.action == 'deletemesh') {
 | 
					        } else if (event.action == 'deletemesh') {
 | 
				
			||||||
            // Stop managing this device group
 | 
					            // Stop managing this device group
 | 
				
			||||||
            stopManagement(event.meshid);
 | 
					            stopManagement(event.meshid);
 | 
				
			||||||
 | 
					        } else if ((event.action == 'meshchange') && (event.relayid != null)) {
 | 
				
			||||||
 | 
					            // See if the relayid changed
 | 
				
			||||||
 | 
					            changeManagementRelayId(event.meshid, event.relayid);
 | 
				
			||||||
        } else if ((event.action == 'turnon') || (event.action == 'turnoff')) {
 | 
					        } else if ((event.action == 'turnon') || (event.action == 'turnoff')) {
 | 
				
			||||||
            // Perform power operation
 | 
					            // Perform power operation
 | 
				
			||||||
            const manager = obj.managedGroups[event.meshid];
 | 
					            const manager = obj.managedGroups[event.meshid];
 | 
				
			||||||
| 
						 | 
					@ -73,8 +76,7 @@ function CreateIPKVMManager(parent) {
 | 
				
			||||||
            manager.onStateChanged = onStateChanged;
 | 
					            manager.onStateChanged = onStateChanged;
 | 
				
			||||||
            manager.onPortsChanged = onPortsChanged;
 | 
					            manager.onPortsChanged = onPortsChanged;
 | 
				
			||||||
            manager.start();
 | 
					            manager.start();
 | 
				
			||||||
        }
 | 
					        } else if (mesh.kvm.model == 2) { // WebPowerSwitch 7
 | 
				
			||||||
        else if (mesh.kvm.model == 2) { // WebPowerSwitch 7
 | 
					 | 
				
			||||||
            const manager = CreateWebPowerSwitch(obj, host, port, mesh.kvm.user, mesh.kvm.pass);
 | 
					            const manager = CreateWebPowerSwitch(obj, host, port, mesh.kvm.user, mesh.kvm.pass);
 | 
				
			||||||
            manager.meshid = mesh._id;
 | 
					            manager.meshid = mesh._id;
 | 
				
			||||||
            manager.relayid = mesh.relayid;
 | 
					            manager.relayid = mesh.relayid;
 | 
				
			||||||
| 
						 | 
					@ -103,6 +105,12 @@ function CreateIPKVMManager(parent) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Change the relayid of a managed device if needed
 | 
				
			||||||
 | 
					    function changeManagementRelayId(meshid, relayid) {
 | 
				
			||||||
 | 
					        const manager = obj.managedGroups[meshid];
 | 
				
			||||||
 | 
					        if ((manager != null) && (manager.relayid != null) && (manager.relayid != relayid)) { manager.updateRelayId(relayid); }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Called when a KVM device changes state
 | 
					    // Called when a KVM device changes state
 | 
				
			||||||
    function onStateChanged(sender, state) {
 | 
					    function onStateChanged(sender, state) {
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
| 
						 | 
					@ -342,7 +350,12 @@ function CreateRaritanKX3Manager(parent, hostname, port, username, password) {
 | 
				
			||||||
    obj.start = function () {
 | 
					    obj.start = function () {
 | 
				
			||||||
        if (obj.started) return;
 | 
					        if (obj.started) return;
 | 
				
			||||||
        obj.started = true;
 | 
					        obj.started = true;
 | 
				
			||||||
        if (obj.state == 0) connect();
 | 
					        if (obj.relayid) {
 | 
				
			||||||
 | 
					            obj.router = CreateMiniRouter(parent, obj.relayid, hostname, port);
 | 
				
			||||||
 | 
					            obj.router.start(function () { connect(); });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            connect();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obj.stop = function () {
 | 
					    obj.stop = function () {
 | 
				
			||||||
| 
						 | 
					@ -350,6 +363,13 @@ function CreateRaritanKX3Manager(parent, hostname, port, username, password) {
 | 
				
			||||||
        obj.started = false;
 | 
					        obj.started = false;
 | 
				
			||||||
        if (retryTimer != null) { clearTimeout(retryTimer); retryTimer = null; }
 | 
					        if (retryTimer != null) { clearTimeout(retryTimer); retryTimer = null; }
 | 
				
			||||||
        setState(0);
 | 
					        setState(0);
 | 
				
			||||||
 | 
					        if (obj.router) { obj.router.stop(); delete obj.router; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If the relay device has changed, update our router
 | 
				
			||||||
 | 
					    obj.updateRelayId = function (relayid) {
 | 
				
			||||||
 | 
					        obj.relayid = relayid;
 | 
				
			||||||
 | 
					        if (obj.router != null) { obj.router.nodeid = relayid; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function setState(newState) {
 | 
					    function setState(newState) {
 | 
				
			||||||
| 
						 | 
					@ -421,6 +441,7 @@ function CreateRaritanKX3Manager(parent, hostname, port, username, password) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function fetchInitialInformation() {
 | 
					    function fetchInitialInformation() {
 | 
				
			||||||
        obj.fetch('/webs_cron.asp?_portsstatushash=&_devicesstatushash=&webs_job=sidebarupdates', null, null, function (server, tag, data) {
 | 
					        obj.fetch('/webs_cron.asp?_portsstatushash=&_devicesstatushash=&webs_job=sidebarupdates', null, null, function (server, tag, data) {
 | 
				
			||||||
 | 
					            data = data.toString();
 | 
				
			||||||
            const parsed = parseJsScript(data);
 | 
					            const parsed = parseJsScript(data);
 | 
				
			||||||
            for (var i in parsed['updateSidebarPanel']) {
 | 
					            for (var i in parsed['updateSidebarPanel']) {
 | 
				
			||||||
                if (parsed['updateSidebarPanel'][i][0] == "cron_device") {
 | 
					                if (parsed['updateSidebarPanel'][i][0] == "cron_device") {
 | 
				
			||||||
| 
						 | 
					@ -558,8 +579,8 @@ function CreateRaritanKX3Manager(parent, hostname, port, username, password) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var data = [];
 | 
					        var data = [];
 | 
				
			||||||
        const options = {
 | 
					        const options = {
 | 
				
			||||||
            hostname: hostname,
 | 
					            hostname: obj.router ? 'localhost' : hostname,
 | 
				
			||||||
            port: port,
 | 
					            port: obj.router ? obj.router.tcpServerPort : port,
 | 
				
			||||||
            rejectUnauthorized: false,
 | 
					            rejectUnauthorized: false,
 | 
				
			||||||
            checkServerIdentity: onCheckServerIdentity,
 | 
					            checkServerIdentity: onCheckServerIdentity,
 | 
				
			||||||
            path: url,
 | 
					            path: url,
 | 
				
			||||||
| 
						 | 
					@ -795,6 +816,12 @@ function CreateWebPowerSwitch(parent, hostname, port, username, password) {
 | 
				
			||||||
        if (obj.router) { obj.router.stop(); delete obj.router; }
 | 
					        if (obj.router) { obj.router.stop(); delete obj.router; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If the relay device has changed, update our router
 | 
				
			||||||
 | 
					    obj.updateRelayId = function (relayid) {
 | 
				
			||||||
 | 
					        obj.relayid = relayid;
 | 
				
			||||||
 | 
					        if (obj.router != null) { obj.router.nodeid = relayid; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function setState(newState) {
 | 
					    function setState(newState) {
 | 
				
			||||||
        if (obj.state == newState) return;
 | 
					        if (obj.state == newState) return;
 | 
				
			||||||
        obj.state = newState;
 | 
					        obj.state = newState;
 | 
				
			||||||
| 
						 | 
					@ -860,7 +887,6 @@ function CreateWebPowerSwitch(parent, hostname, port, username, password) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obj.fetch = function (url, method, data, tag, func) {
 | 
					    obj.fetch = function (url, method, data, tag, func) {
 | 
				
			||||||
        //console.log('fetch', url, method, data, tag);
 | 
					 | 
				
			||||||
        if (obj.state == 0) return;
 | 
					        if (obj.state == 0) return;
 | 
				
			||||||
        if (typeof data == 'string') { data = Buffer.from(data); }
 | 
					        if (typeof data == 'string') { data = Buffer.from(data); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -972,10 +998,12 @@ function CreateMiniRouter(parent, nodeid, targetHost, targetPort) {
 | 
				
			||||||
    function closeTcpSocket(tcpSocket) {
 | 
					    function closeTcpSocket(tcpSocket) {
 | 
				
			||||||
        if (tcpSockets[tcpSocket]) {
 | 
					        if (tcpSockets[tcpSocket]) {
 | 
				
			||||||
            delete tcpSockets[tcpSocket];
 | 
					            delete tcpSockets[tcpSocket];
 | 
				
			||||||
            try { tcpSocket.close(); } catch (ex) { }
 | 
					            try { tcpSocket.end(); } catch (ex) { console.log(ex); }
 | 
				
			||||||
            if (tcpSocket.relaySocket) { try { tcpSocket.relaySocket.close(); } catch (ex) { } }
 | 
					            if (tcpSocket.relaySocket) { try { tcpSocket.relaySocket.close(); } catch (ex) { console.log(ex); } }
 | 
				
			||||||
            delete tcpSocket.relaySocket.tcpSocket;
 | 
					            if (tcpSocket) {
 | 
				
			||||||
            delete tcpSocket.relaySocket;
 | 
					                delete tcpSocket.relaySocket.tcpSocket;
 | 
				
			||||||
 | 
					                delete tcpSocket.relaySocket;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -991,19 +1019,19 @@ function CreateMiniRouter(parent, nodeid, targetHost, targetPort) {
 | 
				
			||||||
        obj.tcpServer.listen(0, 'localhost', function () {
 | 
					        obj.tcpServer.listen(0, 'localhost', function () {
 | 
				
			||||||
            obj.tcpServerPort = obj.tcpServer.address().port;
 | 
					            obj.tcpServerPort = obj.tcpServer.address().port;
 | 
				
			||||||
            parent.parent.debug('relay', 'MiniRouter: Request for relay ' + obj.targetHost + ':' + obj.targetPort + ' started on port ' + obj.tcpServerPort);
 | 
					            parent.parent.debug('relay', 'MiniRouter: Request for relay ' + obj.targetHost + ':' + obj.targetPort + ' started on port ' + obj.tcpServerPort);
 | 
				
			||||||
            onReadyFunc(obj.tcpServerPort);
 | 
					            onReadyFunc(obj.tcpServerPort, obj);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        obj.tcpServer.on('connection', function (socket) {
 | 
					        obj.tcpServer.on('connection', function (socket) {
 | 
				
			||||||
            tcpSockets[socket] = 1;
 | 
					            tcpSockets[socket] = 1;
 | 
				
			||||||
            socket.pause();
 | 
					            socket.pause();
 | 
				
			||||||
            socket.on('data', function (chunk) { // Make sure to handle flow control.
 | 
					            socket.on('data', function (chunk) { // Make sure to handle flow control.
 | 
				
			||||||
                console.log('<-- ' + chunk);
 | 
					 | 
				
			||||||
                const f = function sendDone() { sendDone.tcpSocket.resume(); }
 | 
					                const f = function sendDone() { sendDone.tcpSocket.resume(); }
 | 
				
			||||||
                f.tcpSocket = this;
 | 
					                f.tcpSocket = this;
 | 
				
			||||||
                if (this.relaySocket && this.relaySocket.active) { this.pause(); this.relaySocket.send(chunk, f); }
 | 
					                if (this.relaySocket && this.relaySocket.active) { this.pause(); this.relaySocket.send(chunk, f); }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            socket.on('end', function () { close(this); });
 | 
					            socket.on('end', function () { closeTcpSocket(this); });
 | 
				
			||||||
            socket.on('error', function (err) { close(this); });
 | 
					            socket.on('close', function () { closeTcpSocket(this); });
 | 
				
			||||||
 | 
					            socket.on('error', function (err) { closeTcpSocket(this); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Encode the device relay cookie. Note that there is no userid in this cookie.
 | 
					            // Encode the device relay cookie. Note that there is no userid in this cookie.
 | 
				
			||||||
            const domainid = obj.nodeid.split('/')[1];
 | 
					            const domainid = obj.nodeid.split('/')[1];
 | 
				
			||||||
| 
						 | 
					@ -1015,13 +1043,12 @@ function CreateMiniRouter(parent, nodeid, targetHost, targetPort) {
 | 
				
			||||||
            const protocol = (parent.parent.args.tlsoffload) ? 'ws' : 'wss';
 | 
					            const protocol = (parent.parent.args.tlsoffload) ? 'ws' : 'wss';
 | 
				
			||||||
            var domainadd = '';
 | 
					            var domainadd = '';
 | 
				
			||||||
            if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
 | 
					            if ((domain.dns == null) && (domain.id != '')) { domainadd = domain.id + '/' }
 | 
				
			||||||
            const url = protocol + '://localhost:' + parent.parent.args.port + '/' + domainadd + 'meshrelay.ashx?noping=1&auth=' + cookie;  // TODO: &p=10, Protocol 10 is Web-RDP, Specify TCP routing protocol?
 | 
					            const url = protocol + '://localhost:' + parent.parent.args.port + '/' + domainadd + 'meshrelay.ashx?noping=1&hd=1&auth=' + cookie;  // TODO: &p=10, Protocol 10 is Web-RDP, Specify TCP routing protocol?
 | 
				
			||||||
            parent.parent.debug('relay', 'MiniRouter: Connection websocket to ' + url);
 | 
					            parent.parent.debug('relay', 'MiniRouter: Connection websocket to ' + url);
 | 
				
			||||||
            socket.relaySocket = new WebSocket(url, options);
 | 
					            socket.relaySocket = new WebSocket(url, options);
 | 
				
			||||||
            socket.relaySocket.tcpSocket = socket;
 | 
					            socket.relaySocket.tcpSocket = socket;
 | 
				
			||||||
            socket.relaySocket.on('open', function () { parent.parent.debug('relay', 'MiniRouter: Relay websocket open'); });
 | 
					            socket.relaySocket.on('open', function () { parent.parent.debug('relay', 'MiniRouter: Relay websocket open'); });
 | 
				
			||||||
            socket.relaySocket.on('message', function (data) { // Make sure to handle flow control.
 | 
					            socket.relaySocket.on('message', function (data) { // Make sure to handle flow control.
 | 
				
			||||||
                console.log('--> ' + data);
 | 
					 | 
				
			||||||
                if (!this.active) {
 | 
					                if (!this.active) {
 | 
				
			||||||
                    if (data == 'c') {
 | 
					                    if (data == 'c') {
 | 
				
			||||||
                        // Relay Web socket is connected, start data relay
 | 
					                        // Relay Web socket is connected, start data relay
 | 
				
			||||||
| 
						 | 
					@ -1029,7 +1056,6 @@ function CreateMiniRouter(parent, nodeid, targetHost, targetPort) {
 | 
				
			||||||
                        this.tcpSocket.resume();
 | 
					                        this.tcpSocket.resume();
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        // Could not connect web socket, close it
 | 
					                        // Could not connect web socket, close it
 | 
				
			||||||
                        console.log('ERR', data);
 | 
					 | 
				
			||||||
                        closeWebSocket(this);
 | 
					                        closeWebSocket(this);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
| 
						 | 
					@ -1040,7 +1066,7 @@ function CreateMiniRouter(parent, nodeid, targetHost, targetPort) {
 | 
				
			||||||
                    this.tcpSocket.write(data, f);
 | 
					                    this.tcpSocket.write(data, f);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
            socket.relaySocket.on('close', function () { parent.parent.debug('relay', 'MiniRouter: Relay websocket closed'); closeWebSocket(this); });
 | 
					            socket.relaySocket.on('close', function (reasonCode, description) { parent.parent.debug('relay', 'MiniRouter: Relay websocket closed'); closeWebSocket(this); });
 | 
				
			||||||
            socket.relaySocket.on('error', function (err) { parent.parent.debug('relay', 'MiniRouter: Relay websocket error: ' + err); closeWebSocket(this); });
 | 
					            socket.relaySocket.on('error', function (err) { parent.parent.debug('relay', 'MiniRouter: Relay websocket error: ' + err); closeWebSocket(this); });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,7 +141,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
 | 
				
			||||||
    // Disconnect this agent
 | 
					    // Disconnect this agent
 | 
				
			||||||
    obj.close = function (arg) {
 | 
					    obj.close = function (arg) {
 | 
				
			||||||
        if ((arg == 1) || (arg == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Soft disconnect (' + obj.req.clientIp + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
 | 
					        if ((arg == 1) || (arg == null)) { try { ws.close(); parent.parent.debug('relay', 'Relay: Soft disconnect (' + obj.req.clientIp + ')'); } catch (e) { console.log(e); } } // Soft close, close the websocket
 | 
				
			||||||
        if (arg == 2) { try { ws._socket._parent.end(); parent.parent.debug('relay', 'Relay: Hard disconnect (' + obj.req.clientIp + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
 | 
					        if ((arg == 2) || (req.query.hd == 1)) { try { ws._socket._parent.end(); parent.parent.debug('relay', 'Relay: Hard disconnect (' + obj.req.clientIp + ')'); } catch (e) { console.log(e); } } // Hard close, close the TCP socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Aggressive cleanup
 | 
					        // Aggressive cleanup
 | 
				
			||||||
        delete obj.id;
 | 
					        delete obj.id;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2199,7 +2199,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
 | 
				
			||||||
                        db.Set(mesh);
 | 
					                        db.Set(mesh);
 | 
				
			||||||
                        var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msgid: 142, msgArgs: [mesh.name, changesids], msg: change, domain: domain.id, invite: mesh.invite, expireDevs: command.expireDevs, relayid: mesh.relayid };
 | 
					                        var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msgid: 142, msgArgs: [mesh.name, changesids], msg: change, domain: domain.id, invite: mesh.invite, expireDevs: command.expireDevs, relayid: mesh.relayid };
 | 
				
			||||||
                        if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
 | 
					                        if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
 | 
				
			||||||
                        parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id]), obj, event);
 | 
					                        parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id, 'server-editmesh']), obj, event);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Notify the devices that they have changed relay roles
 | 
					                    // Notify the devices that they have changed relay roles
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue