Lots of work on email notification of device connect/disconnect.

This commit is contained in:
Ylian Saint-Hilaire 2021-10-10 12:43:20 -07:00
parent f6888d4e61
commit 44dec3bf87
13 changed files with 349 additions and 97 deletions

View File

@ -820,7 +820,7 @@ module.exports.CreateAmtManager = function (parent) {
else if (response.Body.OSPowerSavingState == 3) { meshPowerState = 2; } // Modern standby (We are going to call this S1); else if (response.Body.OSPowerSavingState == 3) { meshPowerState = 2; } // Modern standby (We are going to call this S1);
// Set OS power state // Set OS power state
if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState); } if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState, null, { name: dev.name }); }
}); });
} else { } else {
// Convert the power state // Convert the power state
@ -830,7 +830,7 @@ module.exports.CreateAmtManager = function (parent) {
if (powerstate < powerConversionTable.length) { meshPowerState = powerConversionTable[powerstate]; } else { powerstate = 6; } if (powerstate < powerConversionTable.length) { meshPowerState = powerConversionTable[powerstate]; } else { powerstate = 6; }
// Set power state // Set power state
if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState); } if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState, null, { name: dev.name }); }
} }
}); });
} }

View File

@ -263,7 +263,7 @@ module.exports.CreateAmtProvisioningServer = function (parent, config) {
// Setup TLS and commit. // Setup TLS and commit.
attemptTlsSync(dev, function (dev) { attemptTlsSync(dev, function (dev) {
dev.consoleMsg('Intel AMT ACM activation completed.'); dev.consoleMsg('Intel AMT ACM activation completed.');
parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, 7); // Report power state as "present" (7). parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, 7, null, { name: dev.name }); // Report power state as "present" (7).
if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(dev.nodeid, 3, dev.aquired.host); } // Request that Intel AMT manager take a look at this device. if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(dev.nodeid, 3, dev.aquired.host); } // Request that Intel AMT manager take a look at this device.
destroyDevice(dev); // We are done, clean up. destroyDevice(dev); // We are done, clean up.
}); });

View File

@ -178,7 +178,7 @@ module.exports.CreateAmtScanner = function (parent) {
if ((scaninfo.state == 1) && (delta >= PeriodicScanTimeout)) { if ((scaninfo.state == 1) && (delta >= PeriodicScanTimeout)) {
// More than 2 minutes without a response, mark the node as unknown state // More than 2 minutes without a response, mark the node as unknown state
scaninfo.state = 0; scaninfo.state = 0;
obj.parent.ClearConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, 4); // Clear connectivity state obj.parent.ClearConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, 4, null, { name: doc.name }); // Clear connectivity state
if (obj.parent.amtManager != null) { obj.parent.amtManager.stopAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); } if (obj.parent.amtManager != null) { obj.parent.amtManager.stopAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); }
} else if ((scaninfo.tcp == null) && ((scaninfo.state == 0) || isNaN(delta) || (delta > PeriodicScanTime))) { } else if ((scaninfo.tcp == null) && ((scaninfo.state == 0) || isNaN(delta) || (delta > PeriodicScanTime))) {
// More than 30 seconds without a response, try TCP detection // More than 30 seconds without a response, try TCP detection
@ -188,7 +188,7 @@ module.exports.CreateAmtScanner = function (parent) {
tag.lastpong = Date.now(); tag.lastpong = Date.now();
if (tag.state == 0) { if (tag.state == 0) {
tag.state = 1; tag.state = 1;
obj.parent.SetConnectivityState(tag.nodeinfo.meshid, tag.nodeinfo._id, tag.lastpong, 4, 7); // Report power state as "present" (7). obj.parent.SetConnectivityState(tag.nodeinfo.meshid, tag.nodeinfo._id, tag.lastpong, 4, 7, null, { name: doc.name }); // Report power state as "present" (7).
if (version != null) { obj.changeAmtState(tag.nodeinfo._id, version, 2, tag.nodeinfo.intelamt.tls); } if (version != null) { obj.changeAmtState(tag.nodeinfo._id, version, 2, tag.nodeinfo.intelamt.tls); }
if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(tag.nodeinfo._id, 3, tag.nodeinfo.host); } if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(tag.nodeinfo._id, 3, tag.nodeinfo.host); }
} }
@ -299,7 +299,7 @@ module.exports.CreateAmtScanner = function (parent) {
scaninfo.nodeinfo.intelamt.ver = majorVersion + '.' + minorVersion; scaninfo.nodeinfo.intelamt.ver = majorVersion + '.' + minorVersion;
scaninfo.nodeinfo.intelamt.state = provisioningState; scaninfo.nodeinfo.intelamt.state = provisioningState;
} }
obj.parent.SetConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, scaninfo.lastpong, 4, 7); // Report power state as "present" (7). obj.parent.SetConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, scaninfo.lastpong, 4, 7, null, { name: scaninfo.nodeinfo.name }); // Report power state as "present" (7).
obj.changeAmtState(scaninfo.nodeinfo._id, scaninfo.nodeinfo.intelamt.ver, provisioningState, scaninfo.nodeinfo.intelamt.tls); obj.changeAmtState(scaninfo.nodeinfo._id, scaninfo.nodeinfo.intelamt.ver, provisioningState, scaninfo.nodeinfo.intelamt.tls);
if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); } if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); }
} }

View File

@ -64,7 +64,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Remove this agent from the webserver list // Remove this agent from the webserver list
if (parent.wsagents[obj.dbNodeKey] == obj) { if (parent.wsagents[obj.dbNodeKey] == obj) {
delete parent.wsagents[obj.dbNodeKey]; delete parent.wsagents[obj.dbNodeKey];
parent.parent.ClearConnectivityState(obj.dbMeshKey, obj.dbNodeKey, 1, null, { remoteaddrport: obj.remoteaddrport }); parent.parent.ClearConnectivityState(obj.dbMeshKey, obj.dbNodeKey, 1, null, { remoteaddrport: obj.remoteaddrport, name: obj.name });
} }
// Remove this agent from the list of agents with bad web certificates // Remove this agent from the list of agents with bad web certificates
@ -119,17 +119,18 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (obj.pongtimer) { clearInterval(obj.pongtimer); delete obj.pongtimer; } if (obj.pongtimer) { clearInterval(obj.pongtimer); delete obj.pongtimer; }
// Perform aggressive cleanup // Perform aggressive cleanup
if (obj.nonce) { delete obj.nonce; } delete obj.name;
if (obj.nodeid) { delete obj.nodeid; } delete obj.nonce;
if (obj.unauth) { delete obj.unauth; } delete obj.nodeid;
if (obj.remoteaddr) { delete obj.remoteaddr; } delete obj.unauth;
if (obj.remoteaddrport) { delete obj.remoteaddrport; } delete obj.remoteaddr;
if (obj.meshid) { delete obj.meshid; } delete obj.remoteaddrport;
if (obj.dbNodeKey) { delete obj.dbNodeKey; } delete obj.meshid;
if (obj.dbMeshKey) { delete obj.dbMeshKey; } delete obj.dbNodeKey;
if (obj.connectTime) { delete obj.connectTime; } delete obj.dbMeshKey;
if (obj.agentInfo) { delete obj.agentInfo; } delete obj.connectTime;
if (obj.agentExeInfo) { delete obj.agentExeInfo; } delete obj.agentInfo;
delete obj.agentExeInfo;
ws.removeAllListeners(['message', 'close', 'error']); ws.removeAllListeners(['message', 'close', 'error']);
}; };
@ -752,6 +753,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
return; return;
} else { } else {
device = nodes[0]; device = nodes[0];
obj.name = device.name;
// This device exists, meshid given by the device must be ignored, use the server side one. // This device exists, meshid given by the device must be ignored, use the server side one.
if ((device.meshid != null) && (device.meshid != obj.dbMeshKey)) { if ((device.meshid != null) && (device.meshid != obj.dbMeshKey)) {
@ -888,7 +890,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
dupAgent.close(3); dupAgent.close(3);
} else { } else {
// Indicate the agent is connected // Indicate the agent is connected
parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1, null, { remoteaddrport: obj.remoteaddrport }); parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1, null, { remoteaddrport: obj.remoteaddrport, name: device.name });
} }
// We are done, ready to communicate with this agent // We are done, ready to communicate with this agent

View File

@ -2081,6 +2081,46 @@ function CreateMeshCentralServer(config, args) {
} }
}; };
// See if we need to notifiy any user of device state change
obj.NotifyUserOfDeviceStateChange = function (meshid, nodeid, connectTime, connectType, powerState, serverid, stateSet, extraInfo) {
// Check if there is a email server for this domain
const meshSplit = meshid.split('/');
if (meshSplit.length != 3) return;
const domainId = meshSplit[1];
const mailserver = obj.config.domains[domainId].mailserver;;
if (mailserver == null) return;
// Get the device group for this device
const mesh = obj.webserver.meshes[meshid];
if ((mesh == null) || (mesh.links == null)) return;
// Check if any user needs email notification
for (var i in mesh.links) {
if (i.startsWith('user/')) {
const user = obj.webserver.users[i];
if ((user != null) && (user.email != null) && (user.emailVerified == true)) {
const meshLinks = user.links[meshid];
if ((meshLinks != null) && (meshLinks.notify != null) && ((meshLinks.notify & 48) != 0)) {
if (stateSet == true) {
if ((meshLinks.notify & 16) != 0) {
mailserver.notifyDeviceConnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
} else {
mailserver.cancelNotifyDeviceDisconnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
}
}
else if (stateSet == false) {
if ((meshLinks.notify & 32) != 0) {
mailserver.notifyDeviceDisconnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
} else {
mailserver.cancelNotifyDeviceConnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
}
}
}
}
}
}
}
// Set the connectivity state of a node and setup the server so that messages can be routed correctly. // Set the connectivity state of a node and setup the server so that messages can be routed correctly.
// meshId: mesh identifier of format mesh/domain/meshidhex // meshId: mesh identifier of format mesh/domain/meshidhex
// nodeId: node identifier of format node/domain/nodeidhex // nodeId: node identifier of format node/domain/nodeidhex
@ -2091,7 +2131,7 @@ function CreateMeshCentralServer(config, args) {
//var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present']; //var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) { obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
//console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid))); //console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid)));
if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState }); } if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState, extraInfo: extraInfo }); }
if (obj.multiServer == null) { if (obj.multiServer == null) {
// Single server mode // Single server mode
@ -2131,6 +2171,9 @@ function CreateMeshCentralServer(config, args) {
const lc = { _id: 'lc' + nodeid, type: 'lastconnect', domain: nodeid.split('/')[1], meshid: meshid, time: Date.now(), cause: 1, connectType: connectType }; const lc = { _id: 'lc' + nodeid, type: 'lastconnect', domain: nodeid.split('/')[1], meshid: meshid, time: Date.now(), cause: 1, connectType: connectType };
if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; } if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; }
obj.db.Set(lc); obj.db.Set(lc);
// Notify any users of device connection
obj.NotifyUserOfDeviceStateChange(meshid, nodeid, connectTime, connectType, powerState, serverid, true, extraInfo);
} }
} else { } else {
// Multi server mode // Multi server mode
@ -2175,6 +2218,9 @@ function CreateMeshCentralServer(config, args) {
if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; } if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; }
obj.db.Set(lc); obj.db.Set(lc);
} }
// Notify any users of device connection
obj.NotifyUserOfDeviceStateChange(meshid, nodeid, connectTime, connectType, powerState, serverid, true, extraInfo);
} }
} }
}; };
@ -2185,7 +2231,7 @@ function CreateMeshCentralServer(config, args) {
// connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 3 = Intel AMT local. // connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 3 = Intel AMT local.
obj.ClearConnectivityState = function (meshid, nodeid, connectType, serverid, extraInfo) { obj.ClearConnectivityState = function (meshid, nodeid, connectType, serverid, extraInfo) {
//console.log('ClearConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + (serverid == null?(''):(', ServerId: ' + serverid))); //console.log('ClearConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + (serverid == null?(''):(', ServerId: ' + serverid)));
if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'ClearConnectivityState', meshid: meshid, nodeid: nodeid, connectType: connectType }); } if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'ClearConnectivityState', meshid: meshid, nodeid: nodeid, connectType: connectType, extraInfo: extraInfo }); }
if (obj.multiServer == null) { if (obj.multiServer == null) {
// Single server mode // Single server mode
@ -2223,6 +2269,9 @@ function CreateMeshCentralServer(config, args) {
// Event the node connection change // Event the node connection change
if (eventConnectChange == 1) { if (eventConnectChange == 1) {
obj.DispatchEvent(obj.webserver.CreateNodeDispatchTargets(meshid, nodeid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, domain: nodeid.split('/')[1], conn: state.connectivity, pwr: state.powerState, nolog: 1, nopeers: 1 }); obj.DispatchEvent(obj.webserver.CreateNodeDispatchTargets(meshid, nodeid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, domain: nodeid.split('/')[1], conn: state.connectivity, pwr: state.powerState, nolog: 1, nopeers: 1 });
// Notify any users of device disconnection
obj.NotifyUserOfDeviceStateChange(meshid, nodeid, Date.now(), connectType, -1, serverid, false, extraInfo);
} }
} else { } else {
// Multi server mode // Multi server mode
@ -2246,6 +2295,9 @@ function CreateMeshCentralServer(config, args) {
// If the node is completely disconnected, clean it up completely // If the node is completely disconnected, clean it up completely
if (state.connectivity == 0) { delete obj.peerConnectivityByNode[serverid][nodeid]; state.powerState = 0; } if (state.connectivity == 0) { delete obj.peerConnectivityByNode[serverid][nodeid]; state.powerState = 0; }
// Notify any users of device disconnection
obj.NotifyUserOfDeviceStateChange(meshid, nodeid, Date.now(), connectType, -1, serverid, false, extraInfo);
} }
// Clear node power state // Clear node power state

View File

@ -448,5 +448,175 @@ module.exports.CreateMeshMail = function (parent, domain) {
}); });
} }
//
// Device connetion and disconnection notifications
//
obj.deviceNotifications = {}; // UserId --> { timer, nodes: nodeid --> connectType }
// A device connected and a user needs to be notified about it.
obj.notifyDeviceConnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
const mesh = parent.webserver.meshes[meshid];
if (mesh == null) return;
// Add the user and start a timer
if (obj.deviceNotifications[user._id] == null) {
obj.deviceNotifications[user._id] = { nodes: {} };
obj.deviceNotifications[user._id].timer = setTimeout(function () { sendDeviceNotifications(user._id); }, 20000);
}
// Add the device
if (obj.deviceNotifications[user._id].nodes[nodeid] == null) {
obj.deviceNotifications[user._id].nodes[nodeid] = { c: connectType }; // This device connection need to be added
} else {
const info = obj.deviceNotifications[user._id].nodes[nodeid];
if ((info.d != null) && ((info.d & connectType) != 0)) {
info.d -= connectType; // This device disconnect cancels out a device connection
if (((info.c == null) || (info.c == 0)) && ((info.d == null) || (info.d == 0))) {
// This device no longer needs a notification
delete obj.deviceNotifications[user._id].nodes[nodeid];
if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
// This user no longer needs a notification
clearTimeout(obj.deviceNotifications[user._id].timer);
delete obj.deviceNotifications[user._id];
}
return;
}
} else {
if (info.c != null) {
info.c |= connectType; // This device disconnect needs to be added
} else {
info.c = connectType; // This device disconnect needs to be added
}
}
}
// Set the device group name
if ((extraInfo != null) && (extraInfo.name != null)) { obj.deviceNotifications[user._id].nodes[nodeid].nn = extraInfo.name; }
obj.deviceNotifications[user._id].nodes[nodeid].mn = mesh.name;
}
// Cancel a device disconnect notification
obj.cancelNotifyDeviceDisconnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
const mesh = parent.webserver.meshes[meshid];
if (mesh == null) return;
if ((obj.deviceNotifications[user._id] != null) && (obj.deviceNotifications[user._id].nodes[nodeid] != null)) {
const info = obj.deviceNotifications[user._id].nodes[nodeid];
if ((info.d != null) && ((info.d & connectType) != 0)) {
info.d -= connectType; // This device disconnect cancels out a device connection
if (((info.c == null) || (info.c == 0)) && ((info.d == null) || (info.d == 0))) {
// This device no longer needs a notification
delete obj.deviceNotifications[user._id].nodes[nodeid];
if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
// This user no longer needs a notification
clearTimeout(obj.deviceNotifications[user._id].timer);
delete obj.deviceNotifications[user._id];
}
}
}
}
}
// A device disconnected and a user needs to be notified about it.
obj.notifyDeviceDisconnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
const mesh = parent.webserver.meshes[meshid];
if (mesh == null) return;
// Add the user and start a timer
if (obj.deviceNotifications[user._id] == null) {
obj.deviceNotifications[user._id] = { nodes: {} };
obj.deviceNotifications[user._id].timer = setTimeout(function () { sendDeviceNotifications(user._id); }, 20000);
}
// Add the device
if (obj.deviceNotifications[user._id].nodes[nodeid] == null) {
obj.deviceNotifications[user._id].nodes[nodeid] = { d: connectType }; // This device disconnect need to be added
} else {
const info = obj.deviceNotifications[user._id].nodes[nodeid];
if ((info.c != null) && ((info.c & connectType) != 0)) {
info.c -= connectType; // This device disconnect cancels out a device connection
if (((info.d == null) || (info.d == 0)) && ((info.c == null) || (info.c == 0))) {
// This device no longer needs a notification
delete obj.deviceNotifications[user._id].nodes[nodeid];
if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
// This user no longer needs a notification
clearTimeout(obj.deviceNotifications[user._id].timer);
delete obj.deviceNotifications[user._id];
}
return;
}
} else {
if (info.d != null) {
info.d |= connectType; // This device disconnect needs to be added
} else {
info.d = connectType; // This device disconnect needs to be added
}
}
}
// Set the device group name
if ((extraInfo != null) && (extraInfo.name != null)) { obj.deviceNotifications[user._id].nodes[nodeid].nn = extraInfo.name; }
obj.deviceNotifications[user._id].nodes[nodeid].mn = mesh.name;
}
// Cancel a device connect notification
obj.cancelNotifyDeviceConnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
const mesh = parent.webserver.meshes[meshid];
if (mesh == null) return;
if ((obj.deviceNotifications[user._id] != null) && (obj.deviceNotifications[user._id].nodes[nodeid] != null)) {
const info = obj.deviceNotifications[user._id].nodes[nodeid];
if ((info.c != null) && ((info.c & connectType) != 0)) {
info.c -= connectType; // This device disconnect cancels out a device connection
if (((info.d == null) || (info.d == 0)) && ((info.c == null) || (info.c == 0))) {
// This device no longer needs a notification
delete obj.deviceNotifications[user._id].nodes[nodeid];
if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
// This user no longer needs a notification
clearTimeout(obj.deviceNotifications[user._id].timer);
delete obj.deviceNotifications[user._id];
}
}
}
}
}
// Send a notification about device connections and disconnections to a user
function sendDeviceNotifications(userid) {
if (obj.deviceNotifications[userid] == null) return;
clearTimeout(obj.deviceNotifications[userid].timer);
var connections = [];
var disconnections = [];
for (var nodeid in obj.deviceNotifications[userid].nodes) {
var info = obj.deviceNotifications[userid].nodes[nodeid];
if ((info.c != null) && (info.c > 0) && (info.nn != null) && (info.mn != null)) {
var c = [];
if (info.c & 1) { c.push("Agent"); }
if (info.c & 2) { c.push("CIRA"); }
if (info.c & 4) { c.push("AMT"); }
if (info.c & 8) { c.push("AMT-Relay"); }
if (info.c & 16) { c.push("MQTT"); }
connections.push(info.mn + ', ' + info.nn + ': ' + c.join(', '));
}
if ((info.d != null) && (info.d > 0) && (info.nn != null) && (info.mn != null)) {
var d = [];
if (info.d & 1) { d.push("Agent"); }
if (info.d & 2) { d.push("CIRA"); }
if (info.d & 4) { d.push("AMT"); }
if (info.d & 8) { d.push("AMT-Relay"); }
if (info.d & 16) { d.push("MQTT"); }
disconnections.push(info.mn + ', ' + info.nn + ': ' + d.join(', '));
}
}
// TODO: Send the email
//console.log('sendDeviceNotifications', connections, disconnections);
delete obj.deviceNotifications[userid];
}
return obj; return obj;
}; };

View File

@ -2112,6 +2112,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
{ {
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here. if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
// 2 = WebPage device connections
// 4 = WebPage device disconnections
// 8 = WebPage device desktop and serial events
// 16 = Email device connections
// 32 = Email device disconnections
var err = null; var err = null;
try { try {
// Change the current user's notification flags for a meshid // Change the current user's notification flags for a meshid

View File

@ -164,10 +164,10 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
if ((ciraArray != null) && ((ciraArray.indexOf(setConnFunc.socket) >= 0))) { // Check if this connection is still present if ((ciraArray != null) && ((ciraArray.indexOf(setConnFunc.socket) >= 0))) { // Check if this connection is still present
if (setConnFunc.socket.tag.connType == 0) { if (setConnFunc.socket.tag.connType == 0) {
// Intel AMT CIRA connection. This connection indicates the remote device is present. // Intel AMT CIRA connection. This connection indicates the remote device is present.
obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 2, 7); // 7 = Present obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 2, 7, null, { name: socket.tag.name }); // 7 = Present
} else if (setConnFunc.socket.tag.connType == 1) { } else if (setConnFunc.socket.tag.connType == 1) {
// Intel AMT Relay connection. This connection does not give any information about the remote device's power state. // Intel AMT Relay connection. This connection does not give any information about the remote device's power state.
obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 8, 0); // 0 = Unknown obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 8, 0, null, { name: socket.tag.name }); // 0 = Unknown
} }
// Intel AMT LMS connection (connType == 2), we don't notify of these connections except telling the Intel AMT manager about them. // Intel AMT LMS connection (connType == 2), we don't notify of these connections except telling the Intel AMT manager about them.
// If the AMT manager is present, start management of this device // If the AMT manager is present, start management of this device
@ -201,9 +201,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
// Update connectivity state // Update connectivity state
if (socket.tag.connType == 0) { if (socket.tag.connType == 0) {
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2); // CIRA obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2, null, { name: socket.tag.name }); // CIRA
} else if (socket.tag.connType == 1) { } else if (socket.tag.connType == 1) {
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8); // Relay obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8, null, { name: socket.tag.name }); // Relay
} }
} }
@ -520,6 +520,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
// Node is already present // Node is already present
var node = nodes[0]; var node = nodes[0];
socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved. socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
socket.tag.name = node.name;
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; } if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
} }
@ -727,6 +728,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
// Node is already present // Node is already present
var node = nodes[0]; var node = nodes[0];
socket.tag.meshid = node.meshid; socket.tag.meshid = node.meshid;
socket.tag.name = node.name;
if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; } if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
} }

View File

@ -69,7 +69,7 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
if (obj.connections[client.xdbNodeKey] == null) { if (obj.connections[client.xdbNodeKey] == null) {
obj.connections[client.xdbNodeKey] = [client]; obj.connections[client.xdbNodeKey] = [client];
parent.SetConnectivityState(client.xdbMeshKey, client.xdbNodeKey, Date.now(), 16, 7); // Indicate this node has a MQTT connection, 7 = Present state parent.SetConnectivityState(client.xdbMeshKey, client.xdbNodeKey, Date.now(), 16, 7, null, { name: nodes[0].name }); // Indicate this node has a MQTT connection, 7 = Present state
} else { } else {
obj.connections[client.xdbNodeKey].push(client); obj.connections[client.xdbNodeKey].push(client);
} }
@ -85,7 +85,7 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
if (i >= 0) { if (i >= 0) {
if (clients.length == 1) { if (clients.length == 1) {
delete obj.connections[this.parent.xdbNodeKey]; delete obj.connections[this.parent.xdbNodeKey];
parent.ClearConnectivityState(this.parent.xdbMeshKey, this.parent.xdbNodeKey, 16); // Remove the MQTT connection for this node parent.ClearConnectivityState(this.parent.xdbMeshKey, this.parent.xdbNodeKey, 16, null, { name: nodes[0].name }); // Remove the MQTT connection for this node
} else { clients.splice(i, 1); } } else { clients.splice(i, 1); }
} }
} }

View File

@ -517,11 +517,11 @@ module.exports.CreateMultiServer = function (parent, args) {
break; break;
} }
case 'SetConnectivityState': { case 'SetConnectivityState': {
obj.parent.SetConnectivityState(msg.meshid, msg.nodeid, msg.connectTime, msg.connectType, msg.powerState, peerServerId); obj.parent.SetConnectivityState(msg.meshid, msg.nodeid, msg.connectTime, msg.connectType, msg.powerState, peerServerId, msg.extraInfo);
break; break;
} }
case 'ClearConnectivityState': { case 'ClearConnectivityState': {
obj.parent.ClearConnectivityState(msg.meshid, msg.nodeid, msg.connectType, peerServerId); obj.parent.ClearConnectivityState(msg.meshid, msg.nodeid, msg.connectType, peerServerId, msg.extraInfo);
break; break;
} }
case 'relay': { case 'relay': {

View File

@ -18334,21 +18334,21 @@
{ {
"cs": "Připojení zařízení", "cs": "Připojení zařízení",
"de": "Geräteverbindungen", "de": "Geräteverbindungen",
"en": "Device connections.", "en": "Device connections",
"es": "Conexiones de dispositivo.", "es": "Conexiones de dispositivo",
"fi": "Laiteyhteydet.", "fi": "Laiteyhteydet",
"fr": "Connexions des appareils.", "fr": "Connexions des appareils",
"hi": "डिवाइस कनेक्शन।", "hi": "डिवाइस कनेक्शन।",
"it": "Connessioni del dispositivo.", "it": "Connessioni del dispositivo",
"ja": "デバイス接続。", "ja": "デバイス接続。",
"ko": "장치가 연결되었습니다.", "ko": "장치가 연결되었습니다",
"nl": "Apparaat verbindingen.", "nl": "Apparaat verbindingen",
"pl": "Połączenia urządzenia.", "pl": "Połączenia urządzenia",
"pt": "Conexões de dispositivos.", "pt": "Conexões de dispositivos",
"pt-br": "Conexões de dispositivos.", "pt-br": "Conexões de dispositivos",
"ru": "Подключения устройств.", "ru": "Подключения устройств",
"sv": "Enhetsanslutningar.", "sv": "Enhetsanslutningar",
"tr": "Cihaz bağlantıları.", "tr": "Cihaz bağlantıları",
"zh-chs": "设备连接。", "zh-chs": "设备连接。",
"zh-cht": "裝置連接。", "zh-cht": "裝置連接。",
"xloc": [ "xloc": [
@ -18359,21 +18359,21 @@
{ {
"cs": "Odpojení zařízení", "cs": "Odpojení zařízení",
"de": "Gerätetrennungen", "de": "Gerätetrennungen",
"en": "Device disconnections.", "en": "Device disconnections",
"es": "Desconexiones de dispositivo.", "es": "Desconexiones de dispositivo",
"fi": "Laitteen irtikytkennät.", "fi": "Laitteen irtikytkennät",
"fr": "Déconnexions des appareils.", "fr": "Déconnexions des appareils",
"hi": "डिवाइस डिस्कनेक्ट।", "hi": "डिवाइस डिस्कनेक्ट।",
"it": "Disconnessioni del dispositivo.", "it": "Disconnessioni del dispositivo",
"ja": "デバイスの切断。", "ja": "デバイスの切断。",
"ko": "장치 연결이 끊어졌습니다.", "ko": "장치 연결이 끊어졌습니다",
"nl": "Apparaat verbroken.", "nl": "Apparaat verbroken",
"pl": "Odłączenia urządzenia.", "pl": "Odłączenia urządzenia",
"pt": "Desconexões de dispositivos.", "pt": "Desconexões de dispositivos",
"pt-br": "Desconexões de dispositivos.", "pt-br": "Desconexões de dispositivos",
"ru": "Отключения устройств.", "ru": "Отключения устройств",
"sv": "Avbrott av enhet.", "sv": "Avbrott av enhet",
"tr": "Cihaz bağlantılarının kesilmesi.", "tr": "Cihaz bağlantılarının kesilmesi",
"zh-chs": "设备断开连接。", "zh-chs": "设备断开连接。",
"zh-cht": "裝置斷開連接。", "zh-cht": "裝置斷開連接。",
"xloc": [ "xloc": [
@ -29049,25 +29049,25 @@
] ]
}, },
{ {
"cs": "Události Intel&reg; AMT desktop a serial.", "cs": "Události Intel&reg; AMT desktop a serial",
"de": "Intel&reg; AMT Desktop- und Seriell-Ereignisse", "de": "Intel&reg; AMT Desktop- und Seriell-Ereignisse",
"en": "Intel&reg; AMT desktop and serial events.", "en": "Intel&reg; AMT desktop and serial events",
"es": "Eventos de escritorio y serial de Intel&reg; AMT.", "es": "Eventos de escritorio y serial de Intel&reg; AMT",
"fi": "Intel&reg; AMT työpöytä ja sarjaliikenne ilmoitukset.", "fi": "Intel&reg; AMT työpöytä ja sarjaliikenne ilmoitukset",
"fr": "Événements de bureau et série Intel&reg; AMT.", "fr": "Événements de bureau et série Intel&reg; AMT",
"hi": "Intel&reg; AMT डेस्कटॉप और सीरियल इवेंट।", "hi": "Intel&reg; AMT डेस्कटॉप और सीरियल इवेंट।",
"it": "ntel & reg; Desktop AMT e eventi seriali.", "it": "ntel & reg; Desktop AMT e eventi seriali",
"ja": "Intel&reg; AMTデスクトップおよびシリアルイベント。", "ja": "Intel&reg; AMTデスクトップおよびシリアルイベント。",
"ko": "Intel&reg; AMT 데스크탑 및 직렬 이벤트.", "ko": "Intel&reg; AMT 데스크탑 및 직렬 이벤트",
"nl": "Intel&reg; AMT desktop- en seriële gebeurtenissen.", "nl": "Intel&reg; AMT desktop- en seriële gebeurtenissen",
"pl": "Zdarzenia pulpitu i połączeń przewodowych Intel® AMT.", "pl": "Zdarzenia pulpitu i połączeń przewodowych Intel® AMT",
"pt": "Intel&reg; Área de trabalho AMT e eventos seriais.", "pt": "Intel&reg; Área de trabalho AMT e eventos seriais",
"pt-br": "Desktop Intel&reg; AMT e eventos seriais.", "pt-br": "Desktop Intel&reg; AMT e eventos seriais",
"ru": "События Intel&reg; AMT desktop или serial.", "ru": "События Intel&reg; AMT desktop или serial",
"sv": "Intel&reg; AMT stationära och seriella händelser.", "sv": "Intel&reg; AMT stationära och seriella händelser",
"tr": "Intel&reg; AMT masaüstü ve seri etkinlikler.", "tr": "Intel&reg; AMT masaüstü ve seri etkinlikler",
"zh-chs": "英特尔&reg;AMT桌面和串行事件", "zh-chs": "英特尔&reg;AMT桌面和串行事件",
"zh-cht": "Intel&reg; AMT桌面和串行事件", "zh-cht": "Intel&reg; AMT桌面和串行事件",
"xloc": [ "xloc": [
"default.handlebars->37->1640", "default.handlebars->37->1640",
"default.handlebars->37->1944" "default.handlebars->37->1944"
@ -40258,25 +40258,25 @@
] ]
}, },
{ {
"cs": "Zvuk upozornění.", "cs": "Zvuk upozornění",
"de": "Benachrichtigungston", "de": "Benachrichtigungston",
"en": "Notification sound.", "en": "Notification sound",
"es": "Sonido de notificación.", "es": "Sonido de notificación",
"fi": "Ilmoitusääni.", "fi": "Ilmoitusääni",
"fr": "Notification sonore.", "fr": "Notification sonore",
"hi": "सूचना ध्वनि।", "hi": "सूचना ध्वनि।",
"it": "Suono di notifica.", "it": "Suono di notifica",
"ja": "通知音", "ja": "通知音",
"ko": "알림 소리.", "ko": "알림 소리",
"nl": "Meldingsgeluid.", "nl": "Meldingsgeluid",
"pl": "Powiadomienie dźwiękowe.", "pl": "Powiadomienie dźwiękowe",
"pt": "Som de notificação.", "pt": "Som de notificação",
"pt-br": "Som de notificação.", "pt-br": "Som de notificação",
"ru": "Звук уведомления", "ru": "Звук уведомления",
"sv": "Notifikations ljud.", "sv": "Notifikations ljud",
"tr": "Bilgilendirme sesi.", "tr": "Bilgilendirme sesi",
"zh-chs": "通知音效", "zh-chs": "通知音效",
"zh-cht": "通知音效", "zh-cht": "通知音效",
"xloc": [ "xloc": [
"default.handlebars->37->1636" "default.handlebars->37->1636"
] ]

View File

@ -10931,11 +10931,11 @@
function account_showAccountNotifySettings() { function account_showAccountNotifySettings() {
if (xxdialogMode) return false; if (xxdialogMode) return false;
var x = ''; var x = '';
x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Notification sound." + '</label></div>'; x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Notification sound" + '</label></div>';
x += '<div><label><input id=p2notifyGroupName type=checkbox />' + "Display device group name" + '</label></div>'; x += '<div><label><input id=p2notifyGroupName type=checkbox />' + "Display device group name" + '</label></div>';
x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Device connections." + '</label></div>'; x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections." + '</label></div>'; x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events." + '</label></div>'; x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events" + '</label></div>';
setDialogMode(2, "Notification Settings", 3, account_showAccountNotifySettingsEx, x); setDialogMode(2, "Notification Settings", 3, account_showAccountNotifySettingsEx, x);
var n = getstore('notifications', 0); var n = getstore('notifications', 0);
Q('p2notifyPlayNotifySound').checked = (n & 1); Q('p2notifyPlayNotifySound').checked = (n & 1);
@ -11344,6 +11344,10 @@
if (meshNotify & 2) { meshNotifyStr.push("Connect"); } if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); } if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); }
if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); } if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); }
if ((features2 & 0x00004000) && (userinfo.emailVerified)) {
if (meshNotify & 16) { meshNotifyStr.push("Email Connect"); }
if (meshNotify & 32) { meshNotifyStr.push("Email Disconnect"); }
}
if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); } if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()')); x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
} }
@ -12262,23 +12266,38 @@
function p20editMeshNotify() { function p20editMeshNotify() {
if (xxdialogMode) return false; if (xxdialogMode) return false;
var meshNotify = 0; var meshNotify = 0;
var emailNotify = ((features2 & 0x00004000) && (userinfo.emailVerified));
if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; } if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
var x = "Notification settings must also be turned on in account settings." + '<br /><br />'; //var x = "Notification settings must also be turned on in account settings." + '<br /><br />';
x += '<div><label><input id=p20notifyIntelDeviceConnect type=checkbox />' + "Device connections." + '</label></div>'; var x = '<div style="border-bottom: 1px solid #888;margin-bottom:3px">Web Page Notifications</div>';
x += '<div><label><input id=p20notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections." + '</label></div>'; x += '<div><label><input id=p20notifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
x += '<div><label><input id=p20notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events." + '</label></div>'; x += '<div><label><input id=p20notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
setDialogMode(2, "Notification Settings", 3, p20editMeshNotifyEx, x); x += '<div><label><input id=p20notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events" + '</label></div>';
if (emailNotify) {
x += '<br /><div style="border-bottom: 1px solid #888;margin-bottom:3px">Email Notifications</div>';
x += '<div><label><input id=p20enotifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
x += '<div><label><input id=p20enotifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
}
setDialogMode(2, "Notification Settings", 3, p20editMeshNotifyEx, x, emailNotify);
Q('p20notifyIntelDeviceConnect').checked = (meshNotify & 2); Q('p20notifyIntelDeviceConnect').checked = (meshNotify & 2);
Q('p20notifyIntelDeviceDisconnect').checked = (meshNotify & 4); Q('p20notifyIntelDeviceDisconnect').checked = (meshNotify & 4);
Q('p20notifyIntelAmtKvmActions').checked = (meshNotify & 8); Q('p20notifyIntelAmtKvmActions').checked = (meshNotify & 8);
if (emailNotify) {
Q('p20enotifyIntelDeviceConnect').checked = (meshNotify & 16);
Q('p20enotifyIntelDeviceDisconnect').checked = (meshNotify & 32);
}
return false; return false;
} }
function p20editMeshNotifyEx() { function p20editMeshNotifyEx(b, emailNotify) {
var meshNotify = 0; var meshNotify = 0;
meshNotify += Q('p20notifyIntelDeviceConnect').checked ? 2 : 0; meshNotify += Q('p20notifyIntelDeviceConnect').checked ? 2 : 0;
meshNotify += Q('p20notifyIntelDeviceDisconnect').checked ? 4 : 0; meshNotify += Q('p20notifyIntelDeviceDisconnect').checked ? 4 : 0;
meshNotify += Q('p20notifyIntelAmtKvmActions').checked ? 8 : 0; meshNotify += Q('p20notifyIntelAmtKvmActions').checked ? 8 : 0;
if (emailNotify) {
meshNotify += Q('p20enotifyIntelDeviceConnect').checked ? 16 : 0;
meshNotify += Q('p20enotifyIntelDeviceDisconnect').checked ? 32 : 0;
}
meshserver.send({ action: 'changemeshnotify', meshid: currentMesh._id, notify: meshNotify }); meshserver.send({ action: 'changemeshnotify', meshid: currentMesh._id, notify: meshNotify });
} }

View File

@ -2829,6 +2829,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (domain.clipboardget == false) { features2 += 0x00000800; } // Disable clipboard get if (domain.clipboardget == false) { features2 += 0x00000800; } // Disable clipboard get
if (domain.clipboardset == false) { features2 += 0x00001000; } // Disable clipboard set if (domain.clipboardset == false) { features2 += 0x00001000; } // Disable clipboard set
if ((typeof domain.desktop == 'object') && (domain.desktop.viewonly == true)) { features2 += 0x00002000; } // Indicates remote desktop is viewonly if ((typeof domain.desktop == 'object') && (domain.desktop.viewonly == true)) { features2 += 0x00002000; } // Indicates remote desktop is viewonly
if (domain.mailserver != null) { features2 += 0x00004000; } // Indicates email server is active
return { features: features, features2: features2 }; return { features: features, features2: features2 };
} }