Improved structure of IP-KVM relay handling.

This commit is contained in:
Ylian Saint-Hilaire 2021-12-06 03:08:54 -08:00
parent 61e38cbe36
commit f36f1c13c7
2 changed files with 61 additions and 42 deletions

View File

@ -161,6 +161,39 @@ function CreateIPKVMManager(parent) {
return 'node/' + domainid + '/' + parent.crypto.createHash('sha384').update(Buffer.from(meshid + '/' + portid)).digest().toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
}
// Parse an incoming HTTP request URL
function parseIpKvmUrl(domain, url) {
const q = require('url').parse(url, true);
const i = q.path.indexOf('/ipkvm.ashx/');
if (i == -1) return null;
const urlargs = q.path.substring(i + 12).split('/');
if (urlargs[0].length != 64) return null;
const nodeid = 'node/' + domain.id + '/' + urlargs[0];
const nid = urlargs[0];
const kvmport = obj.managedPorts[nodeid];
if (kvmport == null) return null;
const kvmmanager = obj.managedGroups[kvmport.meshid];
if (kvmmanager == null) return null;
urlargs.shift();
var relurl = '/' + urlargs.join('/')
if (relurl.endsWith('/.websocket')) { relurl = relurl.substring(0, relurl.length - 11); }
return { relurl: relurl, preurl: q.path.substring(0, i + 76), nodeid: nodeid, nid: nid, kvmmanager: kvmmanager, kvmport: kvmport };
}
// Handle a IP-KVM HTTP get request
obj.handleIpKvmGet = function(domain, req, res, next) {
const reqinfo = parseIpKvmUrl(domain, req.url);
if (reqinfo == null) { next(); return; }
reqinfo.kvmmanager.handleIpKvmGet(domain, reqinfo, req, res, next);
}
// Handle a IP-KVM HTTP websocket request
obj.handleIpKvmWebSocket = function (domain, ws, req) {
const reqinfo = parseIpKvmUrl(domain, req.url);
if (reqinfo == null) { try { ws.close(); } catch (ex) { } return; }
reqinfo.kvmmanager.handleIpKvmWebSocket(domain, reqinfo, ws, req);
}
return obj;
}
@ -422,6 +455,31 @@ function CreateRaritanKX3Manager(hostname, port, username, password) {
req.end();
}
// Handle a IP-KVM HTTP get request
obj.handleIpKvmGet = function (domain, reqinfo, req, res, next) {
if (reqinfo.relurl == '/') { res.redirect(reqinfo.preurl + '/jsclient/Client.asp#portId=' + reqinfo.kvmport.portid); return; }
// Example: /jsclient/Client.asp#portId=P_000d5d20f64c_1
obj.fetch(reqinfo.relurl, null, [res, reqinfo], function (server, args, data, rres) {
const resx = args[0], xreqinfo = args[1];
if (rres.headers['content-type']) { resx.set('content-type', rres.headers['content-type']); }
// We need to replace the WebSocket code in one of the files to make it work with our server.
// Replace "b=new WebSocket(e+"//"+c+"/"+g);" in file "/js/js_kvm_client.1604062083669.min.js"
if (xreqinfo.relurl.startsWith('/js/js_kvm_client.')) {
data = data.replace('b=new WebSocket(e+"//"+c+"/"+g);', 'b=new WebSocket(e+"//"+c+"/ipkvm.ashx/' + xreqinfo.nid + '/"+g);');
}
resx.end(data);
});
}
// Handle a IP-KVM HTTP websocket request
obj.handleIpKvmWebSocket = function (domain, reqinfo, ws, req) {
//console.log('handleIpKvmWebSocket', reqinfo.preurl);
// TODO
}
return obj;
}

View File

@ -5853,51 +5853,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
obj.app.ws(url + 'ipkvm.ashx/*', function (ws, req) {
const domain = getDomain(req);
if (domain == null) { parent.debug('web', 'ipkvm: failed domain checks.'); try { ws.close(); } catch (ex) { } return; }
const q = require('url').parse(req.url, true);
const i = q.path.indexOf('/ipkvm.ashx/');
if (i == -1) { parent.debug('web', 'ipkvm: failed url checks.'); try { ws.close(); } catch (ex) { } return; }
const urlargs = q.path.substring(i + 12).split('/');
if (urlargs[0].length != 64) { parent.debug('web', 'ipkvm: failed nodeid length checks.'); try { ws.close(); } catch (ex) { } return; }
const nodeid = 'node/' + domain.id + '/' + urlargs[0];
const nid = urlargs[0];
const kvmport = parent.ipKvmManager.managedPorts[nodeid];
if (kvmport == null) { parent.debug('web', 'ipkvm: failed port checks.'); try { ws.close(); } catch (ex) { } return; }
const kvmmanager = parent.ipKvmManager.managedGroups[kvmport.meshid];
if (kvmmanager == null) { parent.debug('web', 'ipkvm: failed manager checks.'); try { ws.close(); } catch (ex) { } return; }
urlargs.shift();
var relurl = '/' + urlargs.join('/')
if (relurl.endsWith('/.websocket')) { relurl = relurl.substring(0, relurl.length - 11); }
console.log('ws', relurl); // TODO
parent.ipKvmManager.handleIpKvmWebSocket(domain, ws, req);
});
obj.app.get(url + 'ipkvm.ashx/*', function (req, res, next) {
const domain = getDomain(req);
if (domain == null) { return; }
const q = require('url').parse(req.url, true);
const i = q.path.indexOf('/ipkvm.ashx/');
if (i == -1) { next(); return; }
const urlargs = q.path.substring(i + 12).split('/');
if (urlargs[0].length != 64) { next(); return; }
const nodeid = 'node/' + domain.id + '/' + urlargs[0];
const nid = urlargs[0];
const kvmport = parent.ipKvmManager.managedPorts[nodeid];
if (kvmport == null) { next(); return; }
const kvmmanager = parent.ipKvmManager.managedGroups[kvmport.meshid];
if (kvmmanager == null) { next(); return; }
urlargs.shift();
const relurl = '/' + urlargs.join('/') + '#portId=' + kvmport.portid;
// Example: /jsclient/Client.asp#portId=P_000d5d20f64c_1
kvmmanager.fetch(relurl, null, [res, nid], function (server, args, data, rres) {
const resx = args[0], nidx = args[1];
if (rres.headers['content-type']) { resx.set('content-type', rres.headers['content-type']); }
// We need to replace the WebSocket code in one of the files to make it work with our server.
// Replace "b=new WebSocket(e+"//"+c+"/"+g);" in file "/js/js_kvm_client.1604062083669.min.js"
if (relurl.startsWith('/js/js_kvm_client.')) {
data = data.replace('b=new WebSocket(e+"//"+c+"/"+g);', 'b=new WebSocket(e+"//"+c+"/ipkvm.ashx/' + nidx + '/"+g);');
}
resx.end(data);
});
if (domain == null) return;
parent.ipKvmManager.handleIpKvmGet(domain, req, res, next);
});
}