Added remote desktop metadata support.

This commit is contained in:
Ylian Saint-Hilaire 2020-05-06 23:23:27 -07:00
parent 268cd82b7d
commit 20f07844c5
9 changed files with 1198 additions and 1099 deletions

View File

@ -228,8 +228,7 @@ function createMeshCore(agent) {
if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); } if (cert.tls) { ddb.Put('SelfNodeTlsCert', cert.tls.pfx); }
if (proxyConfig) { if (proxyConfig) {
ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port); ddb.Put('WebProxy', proxyConfig.host + ':' + proxyConfig.port);
} } else {
else {
ddb.Put('ignoreProxyFile', '1'); ddb.Put('ignoreProxyFile', '1');
} }
@ -1395,18 +1394,34 @@ function createMeshCore(agent) {
this.httprequest.desktop.kvm.parent = this.httprequest.desktop; this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
this.desktop = this.httprequest.desktop; this.desktop = this.httprequest.desktop;
// Add ourself to the list of remote desktop sessions
if (this.httprequest.desktop.kvm.tunnels == null) { this.httprequest.desktop.kvm.tunnels = []; }
this.httprequest.desktop.kvm.tunnels.push(this);
// Send a metadata update to all desktop sessions
var users = {};
for (var i in this.httprequest.desktop.kvm.tunnels) { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } }
for (var i in this.httprequest.desktop.kvm.tunnels) { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); }
this.end = function () { this.end = function () {
--this.desktop.kvm.connectionCount; --this.desktop.kvm.connectionCount;
// Remove ourself from the list of remote desktop session
var i = this.desktop.kvm.tunnels.indexOf(this);
if (i >= 0) { this.desktop.kvm.tunnels.splice(i, 1); }
// Send a metadata update to all desktop sessions
var users = {};
for (var i in this.httprequest.desktop.kvm.tunnels) { var userid = this.httprequest.desktop.kvm.tunnels[i].httprequest.userid; if (users[userid] == null) { users[userid] = 1; } else { users[userid]++; } }
for (var i in this.httprequest.desktop.kvm.tunnels) { this.httprequest.desktop.kvm.tunnels[i].write(JSON.stringify({ ctrlChannel: '102938', type: 'metadata', users: users })); }
// Unpipe the web socket // Unpipe the web socket
try try
{ {
this.unpipe(this.httprequest.desktop.kvm); this.unpipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.unpipe(this); this.httprequest.desktop.kvm.unpipe(this);
} }
catch(xx) catch(ex) { }
{
}
// Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends). // Unpipe the WebRTC channel if needed (This will also be done when the WebRTC channel ends).
if (this.rtcchannel) if (this.rtcchannel)
@ -1416,9 +1431,7 @@ function createMeshCore(agent) {
this.rtcchannel.unpipe(this.httprequest.desktop.kvm); this.rtcchannel.unpipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.unpipe(this.rtcchannel); this.httprequest.desktop.kvm.unpipe(this.rtcchannel);
} }
catch(xx) catch(ex) { }
{
}
} }
// Place wallpaper back if needed // Place wallpaper back if needed
@ -1434,8 +1447,7 @@ function createMeshCore(agent) {
this.httprequest.desktop.kvm.connectionBar.close(); this.httprequest.desktop.kvm.connectionBar.close();
this.httprequest.desktop.kvm.connectionBar = null; this.httprequest.desktop.kvm.connectionBar = null;
} }
} } else {
else {
for (var i in this.httprequest.desktop.kvm.users) { for (var i in this.httprequest.desktop.kvm.users) {
if (this.httprequest.desktop.kvm.users[i] == this.httprequest.username && this.httprequest.desktop.kvm.connectionBar) { if (this.httprequest.desktop.kvm.users[i] == this.httprequest.username && this.httprequest.desktop.kvm.connectionBar) {
this.httprequest.desktop.kvm.users.splice(i, 1); this.httprequest.desktop.kvm.users.splice(i, 1);

View File

@ -132,6 +132,9 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msg: "Joined desktop multiplex session", protocol: 2 }; var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msg: "Joined desktop multiplex session", protocol: 2 };
parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event); parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event);
} }
// Send an updated list of all peers to all viewers
obj.sendSessionMetadata();
} else { } else {
//console.log('addPeer-agent', obj.nodeid); //console.log('addPeer-agent', obj.nodeid);
if (obj.agent != null) return false; if (obj.agent != null) return false;
@ -169,15 +172,17 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
obj.agent = null; obj.agent = null;
// Agent has disconnected, disconnect everyone. // Agent has disconnected, disconnect everyone.
for (var i in obj.viewers) { obj.viewers[i].close(); } if (obj.viewers != null) { for (var i in obj.viewers) { obj.viewers[i].close(); } }
dispose(); dispose();
return true; return true;
} else { } else {
//console.log('removePeer-viewer', obj.nodeid); //console.log('removePeer-viewer', obj.nodeid);
// Remove a viewer // Remove a viewer
var i = obj.viewers.indexOf(peer); if (obj.viewers != null) {
if (i == -1) return false; var i = obj.viewers.indexOf(peer);
obj.viewers.splice(i, 1); if (i == -1) return false;
obj.viewers.splice(i, 1);
}
// Resume flow control if this was the peer that was limiting traffic (because it was the fastest one). // Resume flow control if this was the peer that was limiting traffic (because it was the fastest one).
if (peer.overflow == true) { if (peer.overflow == true) {
@ -205,6 +210,9 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
// If this is the last viewer, disconnect the agent // If this is the last viewer, disconnect the agent
if ((obj.viewers.length == 0) && (obj.agent != null)) { obj.agent.close(); dispose(); return true; } if ((obj.viewers.length == 0) && (obj.agent != null)) { obj.agent.close(); dispose(); return true; }
// Send an updated list of all peers to all viewers
obj.sendSessionMetadata();
} }
return false; return false;
} }
@ -294,6 +302,13 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
} }
} }
// Send the list of all users currently vieweing this session to all viewers
obj.sendSessionMetadata = function () {
var allUsers = {};
for (var i in obj.viewers) { var v = obj.viewers[i]; if ((v.user != null) && (v.user._id != null)) { if (allUsers[v.user._id] == null) { allUsers[v.user._id] = 1; } else { allUsers[v.user._id]++; } } }
obj.sendToAllViewers(JSON.stringify({ type: 'metadata', 'ctrlChannel': '102938', users: allUsers, startTime: obj.startTime }));
}
// Send this command to all viewers // Send this command to all viewers
obj.sendToAllViewers = function (data) { obj.sendToAllViewers = function (data) {
for (var i in obj.viewers) { obj.sendToViewer(obj.viewers[i], data); } for (var i in obj.viewers) { obj.sendToViewer(obj.viewers[i], data); }

View File

@ -431,7 +431,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
switch (command.action) { switch (command.action) {
case 'pong': { break; } // NOP case 'pong': { break; } // NOP
case 'ping': { try { ws.send(JSON.stringify({ action: 'pong' })); } catch (ex) { } break; } case 'ping': { try { ws.send('{action:"pong"}'); } catch (ex) { } break; }
case 'intersession': case 'intersession':
{ {
// Sends data between sessions of the same user // Sends data between sessions of the same user

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.5.24", "version": "0.5.25",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
obj.meshserver = meshserver; obj.meshserver = meshserver;
obj.authCookie = authCookie; obj.authCookie = authCookie;
obj.rauthCookie = rauthCookie; obj.rauthCookie = rauthCookie;
obj.State = 0; obj.State = 0; // 0 = Disconnected, 1 = Connected, 2 = Connected to server, 3 = End-to-end connection.
obj.nodeid = null; obj.nodeid = null;
obj.options = null; obj.options = null;
obj.socket = null; obj.socket = null;
@ -35,6 +35,10 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
obj.consoleMessage = null; obj.consoleMessage = null;
obj.onConsoleMessageChange = null; obj.onConsoleMessageChange = null;
// Session Metadata
obj.metadata = null;
obj.onMetadataChange = null;
// Private method // Private method
//obj.debug = function (msg) { console.log(msg); } //obj.debug = function (msg) { console.log(msg); }
@ -74,6 +78,9 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
if ((typeof args != 'undefined') && args.redirtrace) { console.log('RedirRecv', controlMsg); } if ((typeof args != 'undefined') && args.redirtrace) { console.log('RedirRecv', controlMsg); }
if (controlMsg.type == 'console') { if (controlMsg.type == 'console') {
obj.setConsoleMessage(controlMsg.msg, controlMsg.msgid, controlMsg.msgargs, controlMsg.timeout); obj.setConsoleMessage(controlMsg.msg, controlMsg.msgid, controlMsg.msgargs, controlMsg.timeout);
} else if (controlMsg.type == 'metadata') {
obj.metadata = controlMsg;
if (obj.onMetadataChange) obj.onMetadataChange(obj.metadata);
} else if ((controlMsg.type == 'rtt') && (typeof controlMsg.time == 'number')) { } else if ((controlMsg.type == 'rtt') && (typeof controlMsg.time == 'number')) {
obj.latency.current = (new Date().getTime()) - controlMsg.time; obj.latency.current = (new Date().getTime()) - controlMsg.time;
if (obj.latency.callbacks != null) { obj.latency.callback(obj.latency.current); } if (obj.latency.callbacks != null) { obj.latency.callback(obj.latency.current); }

View File

@ -1 +1 @@
var MeshServerCreateControl=function(t,e){var o={State:0,connectstate:0,pingTimer:null};return o.authCookie=e,o.trace=!1,o.xxStateChange=function(e,t){if(o.State!=e){var n=o.State;o.State=e,o.onStateChanged&&o.onStateChanged(o,o.State,n,t)}},o.Start=function(){if(0==o.connectstate){o.connectstate=0;var e=window.location.protocol.replace("http","ws")+"//"+window.location.host+t+"control.ashx";o.authCookie&&""!=o.authCookie&&(e+="?auth="+o.authCookie),o.socket=new WebSocket(e),o.socket.onopen=function(e){o.connectstate=1},o.socket.onmessage=o.xxOnMessage,o.socket.onclose=function(e){o.Stop(e.code)},o.xxStateChange(1,0),null!=o.pingTimer&&clearInterval(o.pingTimer),o.pingTimer=setInterval(function(){o.send({action:"ping"})},29e3)}},o.Stop=function(e){o.connectstate=0,o.socket&&(o.socket.close(),delete o.socket),null!=o.pingTimer&&(clearInterval(o.pingTimer),o.pingTimer=null),o.xxStateChange(0,e)},o.xxOnMessage=function(e){var t;1==o.State&&o.xxStateChange(2);try{t=JSON.parse(e.data)}catch(e){return}if("object"==typeof t&&"pong"!=t.action){if("close"==t.action)return t.msg&&console.log(t.msg),void o.Stop(t.cause);o.trace&&console.log("RECV",t),o.onMessage&&o.onMessage(o,t)}},o.send=function(e){null!=o.socket&&1==o.connectstate&&(o.trace&&"ping"!=e.action&&console.log("SEND",e),o.socket.send(JSON.stringify(e)))},o} var MeshServerCreateControl=function(e,t){var o={State:0,connectstate:0,pingTimer:null};return o.authCookie=t,o.trace=!1,o.xxStateChange=function(t,e){if(o.State!=t){var n=o.State;o.State=t,o.onStateChanged&&o.onStateChanged(o,o.State,n,e)}},o.Start=function(){if(0==o.connectstate){o.connectstate=0;var t=window.location.protocol.replace("http","ws")+"//"+window.location.host+e+"control.ashx";o.authCookie&&""!=o.authCookie&&(t+="?auth="+o.authCookie),o.socket=new WebSocket(t),o.socket.onopen=function(t){o.connectstate=1},o.socket.onmessage=o.xxOnMessage,o.socket.onclose=function(t){o.Stop(t.code)},o.xxStateChange(1,0),null!=o.pingTimer&&clearInterval(o.pingTimer),o.pingTimer=setInterval(function(){o.send({action:"ping"})},29e3)}},o.Stop=function(t){o.connectstate=0,o.socket&&(o.socket.close(),delete o.socket),null!=o.pingTimer&&(clearInterval(o.pingTimer),o.pingTimer=null),o.xxStateChange(0,t)},o.xxOnMessage=function(t){var e;1==o.State&&o.xxStateChange(2);try{e=JSON.parse(t.data)}catch(t){return}if("object"==typeof e&&"pong"!=e.action){if("ping"==e.action&&o.send({action:"pong"}),"close"==e.action)return e.msg&&console.log(e.msg),void o.Stop(e.cause);o.trace&&console.log("RECV",e),o.onMessage&&o.onMessage(o,e)}},o.send=function(t){null!=o.socket&&1==o.connectstate&&(o.trace&&"ping"!=t.action&&console.log("SEND",t),o.socket.send(JSON.stringify(t)))},o}

File diff suppressed because it is too large Load Diff

View File

@ -530,7 +530,7 @@
<span id=connectbutton1span><input type=button id=connectbutton1 cmenu="deskConnectButton" value="Connect" onclick=connectDesktop(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span> <span id=connectbutton1span><input type=button id=connectbutton1 cmenu="deskConnectButton" value="Connect" onclick=connectDesktop(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
<span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="HW Connect" title="Connect using Intel AMT hardware KVM" onclick=connectDesktop(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span> <span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="HW Connect" title="Connect using Intel AMT hardware KVM" onclick=connectDesktop(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
<span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value="Disconnect" onclick=connectDesktop(event,0) onkeypress="return false" onkeydown="return false" /></span> <span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value="Disconnect" onclick=connectDesktop(event,0) onkeypress="return false" onkeydown="return false" /></span>
&nbsp;<span id="deskstatus">Disconnected</span> &nbsp;<span id="deskstatus">Disconnected</span><span id="deskmetadata"></span>
</div> </div>
</div> </div>
<div id=deskarea2 style=""> <div id=deskarea2 style="">
@ -5803,6 +5803,7 @@
desktop = xdesk; desktop = xdesk;
if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); } if (desktop.m.SendCompressionLevel) { desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate); }
desktop.onStateChanged = onDesktopStateChange; desktop.onStateChanged = onDesktopStateChange;
desktop.onMetadataChange = function(metadata) { updateMetadata(desktop, 'deskmetadata'); }
desktopNode = currentNode; desktopNode = currentNode;
onDesktopStateChange(desktop, desktop.State); onDesktopStateChange(desktop, desktop.State);
delete multiDesktop[currentNode._id]; delete multiDesktop[currentNode._id];
@ -5818,6 +5819,7 @@
desktopNode = currentNode; desktopNode = currentNode;
updateDesktopButtons(); updateDesktopButtons();
deskAdjust(); deskAdjust();
updateMetadata(desktop, 'deskmetadata');
} }
// Show and enable the right buttons // Show and enable the right buttons
@ -6005,6 +6007,7 @@
p11clearConsoleMsg(); p11clearConsoleMsg();
} }
} }
desktop.onMetadataChange = function(metadata) { updateMetadata(desktop, 'deskmetadata'); }
desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best. desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
desktop.m.ScalingLevel = desktopsettings.scaling; desktop.m.ScalingLevel = desktopsettings.scaling;
if (desktopsettings.framerate) { desktop.m.FrameRateTimer = desktopsettings.framerate; } if (desktopsettings.framerate) { desktop.m.FrameRateTimer = desktopsettings.framerate; }
@ -6026,6 +6029,36 @@
} }
} }
function updateMetadata(conn, elementid) {
var str = '', viewerCount = 0;
if (conn && (conn.State == 3)) {
if (conn.metadata && conn.metadata.users) { for (var i in conn.metadata.users) { viewerCount++; } }
if (viewerCount > 1) { str = '<span onclick=showSessionMetadata(1) style=cursor:pointer>' + format(", {0} watching", viewerCount) + '</span>'; }
}
QH('deskmetadata', str);
if ((conn == desktop) && (xxdialogTag == ('sessionMetadata1'))) { showSessionMetadata(1); }
}
function showSessionMetadata(cid) {
if (xxdialogMode && (xxdialogTag != ('sessionMetadata' + cid))) return;
if (xxdialogMode) { setDialogMode(0); }
var conn = null;
if (cid == 1) { conn = desktop; }
if (conn && conn.metadata) {
var x = '';
if (conn.metadata.startTime) { x += addHtmlValue4("Start Time", printDateTime(new Date(conn.metadata.startTime))); }
if (conn.metadata.users) {
for (var i in conn.metadata.users) {
var val = (conn.metadata.users[i] == 1)?"1 connection":format("{0} connections", conn.metadata.users[i]);
var username = i.split('/')[2];
if ((users != null) && (users[i] != null)) { username = users[i].name; }
x += addHtmlValue4(format("User \"{0}\"", username), val);
}
}
setDialogMode(2, "Session Information", 1, null, x, 'sessionMetadata' + cid);
}
}
function p11clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } } function p11clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
function p12clearConsoleMsg() { QH('p12TermConsoleMsg', ''); QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } } function p12clearConsoleMsg() { QH('p12TermConsoleMsg', ''); QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
function p13clearConsoleMsg() { QH('p13FilesConsoleMsg', ''); QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } } function p13clearConsoleMsg() { QH('p13FilesConsoleMsg', ''); QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } }
@ -6090,6 +6123,7 @@
updateDesktopButtons(); updateDesktopButtons();
deskAdjust(); deskAdjust();
setTimeout(deskAdjust, 50); setTimeout(deskAdjust, 50);
updateMetadata(desktop, 'deskmetadata');
} }
function updateSessionTime() { function updateSessionTime() {