Improved structure of IP-KVM relay handling.

Ylian Saint-Hilaire committed Dec 6, 2021 at 03:08 UTC f36f1c13c7fc58bb38bdead86ee703f67e0c8712
2 files changed +61 -42
meshipkvm.js
+58
@@ -161,6 +161,39 @@ function CreateIPKVMManager(parent) {
161 return 'node/' + domainid + '/' + parent.crypto.createHash('sha384').update(Buffer.from(meshid + '/' + portid)).digest().toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
162 }
163
164 + // Parse an incoming HTTP request URL
165 + function parseIpKvmUrl(domain, url) {
166 + const q = require('url').parse(url, true);
167 + const i = q.path.indexOf('/ipkvm.ashx/');
168 + if (i == -1) return null;
169 + const urlargs = q.path.substring(i + 12).split('/');
170 + if (urlargs[0].length != 64) return null;
171 + const nodeid = 'node/' + domain.id + '/' + urlargs[0];
172 + const nid = urlargs[0];
173 + const kvmport = obj.managedPorts[nodeid];
174 + if (kvmport == null) return null;
175 + const kvmmanager = obj.managedGroups[kvmport.meshid];
176 + if (kvmmanager == null) return null;
177 + urlargs.shift();
178 + var relurl = '/' + urlargs.join('/')
179 + if (relurl.endsWith('/.websocket')) { relurl = relurl.substring(0, relurl.length - 11); }
180 + return { relurl: relurl, preurl: q.path.substring(0, i + 76), nodeid: nodeid, nid: nid, kvmmanager: kvmmanager, kvmport: kvmport };
181 + }
182 +
183 + // Handle a IP-KVM HTTP get request
184 + obj.handleIpKvmGet = function(domain, req, res, next) {
185 + const reqinfo = parseIpKvmUrl(domain, req.url);
186 + if (reqinfo == null) { next(); return; }
187 + reqinfo.kvmmanager.handleIpKvmGet(domain, reqinfo, req, res, next);
188 + }
189 +
190 + // Handle a IP-KVM HTTP websocket request
191 + obj.handleIpKvmWebSocket = function (domain, ws, req) {
192 + const reqinfo = parseIpKvmUrl(domain, req.url);
193 + if (reqinfo == null) { try { ws.close(); } catch (ex) { } return; }
194 + reqinfo.kvmmanager.handleIpKvmWebSocket(domain, reqinfo, ws, req);
195 + }
196 +
197 return obj;
198 }
199
@@ -422,6 +455,31 @@ function CreateRaritanKX3Manager(hostname, port, username, password) {
455 req.end();
456 }
457
458 + // Handle a IP-KVM HTTP get request
459 + obj.handleIpKvmGet = function (domain, reqinfo, req, res, next) {
460 + if (reqinfo.relurl == '/') { res.redirect(reqinfo.preurl + '/jsclient/Client.asp#portId=' + reqinfo.kvmport.portid); return; }
461 +
462 + // Example: /jsclient/Client.asp#portId=P_000d5d20f64c_1
463 + obj.fetch(reqinfo.relurl, null, [res, reqinfo], function (server, args, data, rres) {
464 + const resx = args[0], xreqinfo = args[1];
465 + if (rres.headers['content-type']) { resx.set('content-type', rres.headers['content-type']); }
466 +
467 + // We need to replace the WebSocket code in one of the files to make it work with our server.
468 + // Replace "b=new WebSocket(e+"//"+c+"/"+g);" in file "/js/js_kvm_client.1604062083669.min.js"
469 + if (xreqinfo.relurl.startsWith('/js/js_kvm_client.')) {
470 + data = data.replace('b=new WebSocket(e+"//"+c+"/"+g);', 'b=new WebSocket(e+"//"+c+"/ipkvm.ashx/' + xreqinfo.nid + '/"+g);');
471 + }
472 +
473 + resx.end(data);
474 + });
475 + }
476 +
477 + // Handle a IP-KVM HTTP websocket request
478 + obj.handleIpKvmWebSocket = function (domain, reqinfo, ws, req) {
479 + //console.log('handleIpKvmWebSocket', reqinfo.preurl);
480 + // TODO
481 + }
482 +
483 return obj;
484 }
485
webserver.js
+3 -42
@@ -5853,51 +5853,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
5853 obj.app.ws(url + 'ipkvm.ashx/*', function (ws, req) {
5854 const domain = getDomain(req);
5855 if (domain == null) { parent.debug('web', 'ipkvm: failed domain checks.'); try { ws.close(); } catch (ex) { } return; }
5856 - const q = require('url').parse(req.url, true);
5857 - const i = q.path.indexOf('/ipkvm.ashx/');
5858 - if (i == -1) { parent.debug('web', 'ipkvm: failed url checks.'); try { ws.close(); } catch (ex) { } return; }
5859 - const urlargs = q.path.substring(i + 12).split('/');
5860 - if (urlargs[0].length != 64) { parent.debug('web', 'ipkvm: failed nodeid length checks.'); try { ws.close(); } catch (ex) { } return; }
5861 - const nodeid = 'node/' + domain.id + '/' + urlargs[0];
5862 - const nid = urlargs[0];
5863 - const kvmport = parent.ipKvmManager.managedPorts[nodeid];
5864 - if (kvmport == null) { parent.debug('web', 'ipkvm: failed port checks.'); try { ws.close(); } catch (ex) { } return; }
5865 - const kvmmanager = parent.ipKvmManager.managedGroups[kvmport.meshid];
5866 - if (kvmmanager == null) { parent.debug('web', 'ipkvm: failed manager checks.'); try { ws.close(); } catch (ex) { } return; }
5867 - urlargs.shift();
5868 - var relurl = '/' + urlargs.join('/')
5869 - if (relurl.endsWith('/.websocket')) { relurl = relurl.substring(0, relurl.length - 11); }
5870 - console.log('ws', relurl); // TODO
5856 + parent.ipKvmManager.handleIpKvmWebSocket(domain, ws, req);
5857 });
5858 obj.app.get(url + 'ipkvm.ashx/*', function (req, res, next) {
5859 const domain = getDomain(req);
5874 - if (domain == null) { return; }
5875 - const q = require('url').parse(req.url, true);
5876 - const i = q.path.indexOf('/ipkvm.ashx/');
5877 - if (i == -1) { next(); return; }
5878 - const urlargs = q.path.substring(i + 12).split('/');
5879 - if (urlargs[0].length != 64) { next(); return; }
5880 - const nodeid = 'node/' + domain.id + '/' + urlargs[0];
5881 - const nid = urlargs[0];
5882 - const kvmport = parent.ipKvmManager.managedPorts[nodeid];
5883 - if (kvmport == null) { next(); return; }
5884 - const kvmmanager = parent.ipKvmManager.managedGroups[kvmport.meshid];
5885 - if (kvmmanager == null) { next(); return; }
5886 - urlargs.shift();
5887 - const relurl = '/' + urlargs.join('/') + '#portId=' + kvmport.portid;
5888 - // Example: /jsclient/Client.asp#portId=P_000d5d20f64c_1
5889 - kvmmanager.fetch(relurl, null, [res, nid], function (server, args, data, rres) {
5890 - const resx = args[0], nidx = args[1];
5891 - if (rres.headers['content-type']) { resx.set('content-type', rres.headers['content-type']); }
5892 -
5893 - // We need to replace the WebSocket code in one of the files to make it work with our server.
5894 - // Replace "b=new WebSocket(e+"//"+c+"/"+g);" in file "/js/js_kvm_client.1604062083669.min.js"
5895 - if (relurl.startsWith('/js/js_kvm_client.')) {
5896 - data = data.replace('b=new WebSocket(e+"//"+c+"/"+g);', 'b=new WebSocket(e+"//"+c+"/ipkvm.ashx/' + nidx + '/"+g);');
5897 - }
5898 -
5899 - resx.end(data);
5900 - });
5860 + if (domain == null) return;
5861 + parent.ipKvmManager.handleIpKvmGet(domain, req, res, next);
5862 });
5863 }
5864