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