Improved events and reports.

Ylian Saint-Hilaire committed Sep 12, 2021 at 13:03 UTC 663d1fb7223d483e93003b5a914787add360841b
3 files changed +55 -13
meshdesktopmultiplex.js
+41 -3
@@ -186,11 +186,12 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
186 if (obj.viewers == null) return;
187 if (peer == obj.agent) {
188 //console.log('removePeer-agent', obj.nodeid);
189 + // Agent has disconnected, disconnect everyone.
190 + if (obj.viewers != null) { for (var i in obj.viewers) { obj.viewers[i].close(); } }
191 +
192 // Clean up the agent
193 obj.agent = null;
194
192 - // Agent has disconnected, disconnect everyone.
193 - if (obj.viewers != null) { for (var i in obj.viewers) { obj.viewers[i].close(); } }
195 dispose();
196 return true;
197 } else {
@@ -211,9 +212,46 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
212
213 // Log leaving the multiplex session
214 if (obj.startTime != null) { // Used to check if the agent has connected. If not, don't log this event since the session never really started.
215 + // In this code, we want to compute the share of in/out traffic that belongs to this viewer. It includes all of the viewers in/out traffic + all or a portion of the agents in/out traffic.
216 + // The agent traffic needs to get divided out between the viewers fairly. For the time that multiple viewers are present, the agent traffic is divided between the viewers.
217 +
218 + // Compute traffic to and from the browser
219 + var inTraffc, outTraffc;
220 + try { inTraffc = peer.ws._socket.bytesRead; } catch (ex) { }
221 + try { outTraffc = peer.ws._socket.bytesWritten; } catch (ex) { }
222 +
223 + // Add any previous agent traffic accounting
224 + if (peer.agentInTraffic) { inTraffc += peer.agentInTraffic; }
225 + if (peer.outTraffc) { inTraffc += peer.agentOutTraffic; }
226 +
227 + // Compute traffic to and from the agent
228 + if (obj.agent != null) {
229 + // Get unaccounted bytes from/to the agent
230 + var agentInTraffc, agentOutTraffc, agentInTraffc2, agentOutTraffc2;
231 + try { agentInTraffc = agentInTraffc2 = obj.agent.ws._socket.bytesRead; } catch (ex) { }
232 + try { agentOutTraffc = agentOutTraffc2 = obj.agent.ws._socket.bytesWritten; } catch (ex) { }
233 + if (obj.agent.accountedBytesRead) { agentInTraffc -= obj.agent.accountedBytesRead; }
234 + if (obj.agent.accountedBytesWritten) { agentOutTraffc -= obj.agent.accountedBytesWritten; }
235 + obj.agent.accountedBytesRead = agentInTraffc2;
236 + obj.agent.accountedBytesWritten = agentOutTraffc2;
237 +
238 + // Devide up the agent traffic amoung the viewers
239 + var viewerPartIn = Math.floor(agentInTraffc / (obj.viewers.length + 1));
240 + var viewerPartOut = Math.floor(agentOutTraffc / (obj.viewers.length + 1));
241 +
242 + // Add the portion to this viewer and all other viewer
243 + inTraffc += viewerPartIn;
244 + outTraffc += viewerPartOut;
245 + for (var i in obj.viewers) {
246 + if (obj.viewers[i].agentInTraffic) { obj.viewers[i].agentInTraffic += viewerPartIn; } else { obj.viewers[i].agentInTraffic = viewerPartIn; }
247 + if (obj.viewers[i].agentOutTraffic) { obj.viewers[i].agentOutTraffic += viewerPartOut; } else { obj.viewers[i].agentOutTraffic = viewerPartOut; }
248 + }
249 + }
250 +
251 //var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msgid: 5, msg: "Left the desktop multiplex session", protocol: 2 };
252 const sessionSeconds = Math.floor((Date.now() - peer.startTime) / 1000);
216 - var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msgid: 122, msgArgs: [sessionSeconds], msg: "Left the desktop multiplex session after " + sessionSeconds + " second(s).", protocol: 2 };
253 + var event = { etype: 'relay', action: 'relaylog', domain: domain.id, nodeid: obj.nodeid, userid: peer.user._id, username: peer.user.name, msgid: 122, msgArgs: [sessionSeconds], msg: "Left the desktop multiplex session after " + sessionSeconds + " second(s).", protocol: 2, bytesin: inTraffc, bytesout: outTraffc };
254 + if (peer.guestName) { event.guestname = peer.guestName; }
255 parent.parent.DispatchEvent(['*', obj.nodeid, peer.user._id, obj.meshid], obj, event);
256 }
257
meshuser.js
+10 -7
@@ -4694,8 +4694,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4694 expireTime = command.end * 1000;
4695 }
4696
4697 - //var cookie = { a: 5, p: command.p, uid: user._id, gn: command.guestname, nid: node._id, cf: command.consent, pid: publicid };
4698 - var cookie = { a: 6, pid: publicid };
4697 + //var cookie = { a: 5, p: command.p, uid: user._id, gn: command.guestname, nid: node._id, cf: command.consent, pid: publicid }; // Old style sharing cookie
4698 + var cookie = { a: 6, pid: publicid }; // New style sharing cookie
4699 if ((startTime != null) && (expireTime != null)) { command.start = startTime; command.expire = cookie.e = expireTime; }
4700 const inviteCookie = parent.parent.encodeCookie(cookie, parent.parent.invitationLinkEncryptionKey);
4701 if (inviteCookie == null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'createDeviceShareLink', responseid: command.responseid, result: 'Unable to generate shareing cookie' })); } catch (ex) { } } return; }
@@ -5475,20 +5475,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5475 // Columns
5476 if (command.groupBy == 1) {
5477 data.groupFormat = 'user';
5478 - data.columns = [{ id: 'time', title: "time", format: 'datetime' }, { id: 'nodeid', title: "device", format: 'node' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5478 + data.columns = [{ id: 'time', title: "time", format: 'datetime' }, { id: 'nodeid', title: "device", format: 'node' }, { id: 'guestname', title: "guest", align: 'center' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5479 } else if (command.groupBy == 2) {
5480 data.groupFormat = 'node';
5481 - data.columns = [{ id: 'time', title: "time", format: 'datetime' }, { id: 'userid', title: "user", format: 'user' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5481 + data.columns = [{ id: 'time', title: "time", format: 'datetime' }, { id: 'userid', title: "user", format: 'user' }, { id: 'guestname', title: "guest", align: 'center' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5482 } else if (command.groupBy == 3) {
5483 - data.columns = [{ id: 'time', title: "time", format: 'time' }, { id: 'nodeid', title: "device", format: 'node' }, { id: 'userid', title: "user", format: 'user' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5483 + data.columns = [{ id: 'time', title: "time", format: 'time' }, { id: 'nodeid', title: "device", format: 'node' }, { id: 'guestname', title: "guest", align: 'center' }, { id: 'userid', title: "user", format: 'user' }, { id: 'protocol', title: "session", format: 'protocol', align: 'center' }, { id: 'length', title: "length", format: 'seconds', align: 'center', sumBy: 'protocol' } ];
5484 }
5485
5486 - // Add traffic colums
5486 + // Add traffic columns
5487 if (command.showTraffic) {
5488 data.columns.push({ id: 'bytesin', title: "bytesin", format: 'bytes', align: 'center', sumBy: 'protocol' });
5489 data.columns.push({ id: 'bytesout', title: "bytesout", format: 'bytes', align: 'center', sumBy: 'protocol' });
5490 }
5491
5492 + // Remote guest column is not needed
5493 + if (!command.showGuestName) { data.columns.splice(2, 1); }
5494 +
5495 // Rows
5496 for (var i in docs) {
5497 // If MySQL or MariaDB query, we can't filter on MsgID, so we have to do it here.
@@ -5506,7 +5509,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5509 if (command.showTraffic) { entry.bytesin = docs[i].bytesin; entry.bytesout = docs[i].bytesout; }
5510
5511 // Add guest name if present
5509 - if (docs[i].nodeid.guestname != null) { entry.guestname = docs[i].nodeid.guestname; }
5512 + if (docs[i].guestname != null) { entry.guestname = docs[i].guestname; }
5513
5514 // Session length
5515 if (((docs[i].msgid >= 10) && (docs[i].msgid <= 12)) && (docs[i].msgArgs != null) && (typeof docs[i].msgArgs == 'object') && (typeof docs[i].msgArgs[3] == 'number')) { entry.length = docs[i].msgArgs[3]; }
views/default.handlebars
+4 -3
@@ -14951,6 +14951,7 @@
14951
14952 x += '<div id=d2showTrafficDiv style=display:none>';
14953 x += addHtmlValue("", '<div style=width:250px><label><input type=checkbox id=d2showTraffic ' + ((settings.showTraffic) ? 'checked' : '') + '>' + "Show Traffic" + '</label><div>');
14954 + x += addHtmlValue("", '<div style=width:250px><label><input type=checkbox id=d2showGuestName ' + ((settings.showGuestName) ? 'checked' : '') + '>' + "Show Guest Name" + '</label><div>');
14955 x += '</div>';
14956
14957 setDialogMode(2, "Generate Report", 3, generateReportDialogEx, x);
@@ -14981,12 +14982,12 @@
14982 try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone; } catch (ex) {}
14983 var devGroup = decodeURIComponent(Q('d2groupId').value);
14984 if (devGroup == 0) { devGroup = null; }
14984 - putstore('_ReportSettings', JSON.stringify({ type: parseInt(Q('d2reportType').value), groupBy: parseInt(Q('d2groupBy').value), timeRange: parseInt(Q('d2timeRange').value), devGroup: devGroup, showTraffic: Q('d2showTraffic').checked }));
14985 - meshserver.send({ action: 'report', type: parseInt(Q('d2reportType').value), groupBy: parseInt(Q('d2groupBy').value), start: start, end: end, tz: tz, tf: new Date().getTimezoneOffset(), l: getLang(), devGroup: devGroup, showTraffic: Q('d2showTraffic').checked });
14985 + putstore('_ReportSettings', JSON.stringify({ type: parseInt(Q('d2reportType').value), groupBy: parseInt(Q('d2groupBy').value), timeRange: parseInt(Q('d2timeRange').value), devGroup: devGroup, showTraffic: Q('d2showTraffic').checked, showGuestName: Q('d2showGuestName').checked }));
14986 + meshserver.send({ action: 'report', type: parseInt(Q('d2reportType').value), groupBy: parseInt(Q('d2groupBy').value), start: start, end: end, tz: tz, tf: new Date().getTimezoneOffset(), l: getLang(), devGroup: devGroup, showTraffic: Q('d2showTraffic').checked, showGuestName: Q('d2showGuestName').checked });
14987 }
14988
14989 function renderReport(r) {
14989 - var colTranslation = { time: "Time", device: "Device", session: "Session", user: "User", length: "Length", bytesin: "Bytes In", bytesout: "Bytes Out" }
14990 + var colTranslation = { time: "Time", device: "Device", session: "Session", user: "User", guest: "Guest", length: "Length", bytesin: "Bytes In", bytesout: "Bytes Out" }
14991 var x = '<table style=width:100%>', firstItem;
14992 var sumByCol = null; // Indicate by what colum we sum by
14993 var sumByValues = []; // Indicate by what values we sum by