Fixed server wake-on-lan.
Ylian Saint-Hilaire committed
Apr 23, 2021 at 17:28 UTC
77a46f04ffbab86fd926836ec7509f9df6bb1812
3 files changed
+38
-15
amt/amt.js
+7
@@ -194,6 +194,10 @@ function AmtStackCreateService(wsmanStack) {
194
obj.CIM_PowerManagementService_RequestPowerStateChange(PowerState, "<Address xmlns=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\"><ResourceURI xmlns=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</ResourceURI><SelectorSet xmlns=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\"><Selector Name=\"CreationClassName\">CIM_ComputerSystem</Selector><Selector Name=\"Name\">ManagedSystem</Selector></SelectorSet></ReferenceParameters>", null, null, callback_func);
195
}
196
197
+ obj.RequestOSPowerStateChange = function (PowerState, callback_func) {
198
+ obj.IPS_PowerManagementService_RequestOSPowerSavingStateChange(PowerState, '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="CreationClassName">CIM_ComputerSystem</Selector><Selector Name="Name">ManagedSystem</Selector></SelectorSet></ReferenceParameters>', null, null, callback_func);
199
+ }
200
+
201
obj.SetBootConfigRole = function (Role, callback_func) {
202
obj.CIM_BootService_SetBootConfigRole("<Address xmlns=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\"><ResourceURI xmlns=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BootConfigSetting</ResourceURI><SelectorSet xmlns=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\"><Selector Name=\"InstanceID\">Intel(r) AMT: Boot Configuration 0</Selector></SelectorSet></ReferenceParameters>", Role, callback_func);
203
}
@@ -384,9 +388,12 @@ function AmtStackCreateService(wsmanStack) {
388
obj.IPS_OptInService_StartService = function (callback_func) { obj.Exec("IPS_OptInService", "StartService", {}, callback_func); }
389
obj.IPS_OptInService_StopService = function (callback_func) { obj.Exec("IPS_OptInService", "StopService", {}, callback_func); }
390
obj.IPS_OptInService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_OptInService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
391
+ obj.IPS_PowerManagementService_RequestOSPowerSavingStateChange = function (PowerState, ManagedElement, Time, TimeoutPeriod, callback_func) { obj.Exec('IPS_PowerManagementService', 'RequestOSPowerSavingStateChange', { 'OSPowerSavingState': PowerState, 'ManagedElement': ManagedElement, 'Time': Time, 'TimeoutPeriod': TimeoutPeriod }, callback_func, 0, 1); }
392
obj.IPS_ProvisioningRecordLog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_ProvisioningRecordLog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
393
obj.IPS_ProvisioningRecordLog_ClearLog = function (_method_dummy, callback_func) { obj.Exec("IPS_ProvisioningRecordLog", "ClearLog", { "_method_dummy": _method_dummy }, callback_func); }
394
+ obj.IPS_ScreenConfigurationService_SetSessionState = function (SessionState, ConsecutiveRebootsNum, callback_func) { obj.Exec('IPS_ScreenConfigurationService', 'SetSessionState', { 'SessionState': SessionState, 'ConsecutiveRebootsNum': ConsecutiveRebootsNum }, callback_func); }
395
obj.IPS_SecIOService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_SecIOService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
396
+ obj.IPS_HTTPProxyService_AddProxyAccessPoint = function (AccessInfo, InfoFormat, Port, NetworkDnsSuffix, callback_func) { obj.Exec('IPS_HTTPProxyService', 'AddProxyAccessPoint', { 'AccessInfo': AccessInfo, 'InfoFormat': InfoFormat, 'Port': Port, 'NetworkDnsSuffix': NetworkDnsSuffix }, callback_func); }
397
398
obj.AmtStatusToStr = function (code) { if (obj.AmtStatusCodes[code]) return obj.AmtStatusCodes[code]; else return "UNKNOWN_ERROR" }
399
obj.AmtStatusCodes = {
amtmanager.js
+12
-1
@@ -838,6 +838,7 @@ module.exports.CreateAmtManager = function (parent) {
838
// If not LMS, has a AMT stack present and is in connected state, perform power operation.
839
if ((dev.connType != 2) && (dev.state == 1) && (dev.amtstack != null)) {
840
// Action: 2 = Power on, 8 = Power down, 10 = reset
841
+ dev.powerAction = action;
842
try { dev.amtstack.RequestPowerStateChange(action, performPowerActionResponse); } catch (ex) { }
843
}
844
}
@@ -845,7 +846,17 @@ module.exports.CreateAmtManager = function (parent) {
846
847
// Response to Intel AMT power action
848
function performPowerActionResponse(stack, name, responses, status) {
848
- //console.log('performPowerActionResponse', status);
849
+ const dev = stack.dev;
850
+ const action = dev.powerAction;
851
+ delete dev.powerAction;
852
+ if (obj.amtDevices[dev.nodeid] == null) return; // Device no longer exists, ignore this response.
853
+ if (status != 200) return;
854
+
855
+ // If this is Intel AMT 10 or higher and we are trying to wake the device, send an OS wake.
856
+ // This will wake the device from "Modern Standby".
857
+ if ((action == 2) && (dev.aquired.majorver > 9)) {
858
+ try { dev.amtstack.RequestOSPowerStateChange(2, function (stack, name, response, status) { }); } catch (ex) { }
859
+ }
860
}
861
862
meshscanner.js
+19
-14
@@ -28,6 +28,8 @@ module.exports.CreateMeshScanner = function (parent) {
28
const membershipIPv6 = 'FF02:0:0:0:0:0:0:FE';
29
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }).toUpperCase();
30
obj.error = 0;
31
+ obj.pendingOutboundPackets = [];
32
+ obj.pendingOutboundTimer = null;
33
34
// Setup the multicast key if present
35
if ((typeof obj.parent.args.localdiscovery == 'object') && (typeof obj.parent.args.localdiscovery.key == 'string') && (obj.parent.args.localdiscovery.key.length > 0)) {
@@ -227,34 +229,37 @@ module.exports.CreateMeshScanner = function (parent) {
229
}
230
}
231
232
+ // Send the next packet in the pending list, stop the timer if we are done.
233
+ function sendPendingPacket() {
234
+ if (obj.pendingOutboundPackets.length == 0) { if (obj.pendingOutboundTimer != null) { clearInterval(obj.pendingOutboundTimer); obj.pendingOutboundTimer = null; } return; }
235
+ var packet = obj.pendingOutboundPackets.shift();
236
+ if (packet != null) { packet[0].send(packet[1], 0, packet[1].length, packet[2], packet[3]); }
237
+ }
238
+
239
// As a side job, we also send server wake-on-lan packets
240
obj.wakeOnLan = function (macs, host) {
232
- var i, j;
241
+ var i, j, futureTime = 0;
242
for (i in macs) {
243
var mac = macs[i].split(':').join('');
244
var hexpacket = 'FFFFFFFFFFFF';
245
for (j = 0; j < 16; j++) { hexpacket += mac; }
246
var wakepacket = Buffer.from(hexpacket, 'hex');
238
- //console.log(wakepacket.toString('hex'));
247
240
- // Setup the wake function
241
- const func = function wakeFunc() {
248
+ // Add all wake packets to the pending list
249
+ for (var k = 0; k < 2; k++) {
250
for (j in obj.servers4) {
243
- obj.servers4[j].send(wakeFunc.wakepacket, 0, wakeFunc.wakepacket.length, 7, '255.255.255.255');
244
- obj.servers4[j].send(wakeFunc.wakepacket, 0, wakeFunc.wakepacket.length, 16990, membershipIPv4);
245
- if (wakeFunc.host != null) { obj.servers4[j].send(wakeFunc.wakepacket, 0, wakeFunc.wakepacket.length, 7, wakeFunc.host); }
251
+ obj.pendingOutboundPackets.push([obj.servers4[j], wakepacket, 7, '255.255.255.255']); // IPv4 Broadcast
252
+ obj.pendingOutboundPackets.push([obj.servers4[j], wakepacket, 16990, membershipIPv4]); // IPv4 Multicast
253
+ if (host != null) { obj.pendingOutboundPackets.push([obj.servers4[j], wakepacket, 7, host]); } // IPv4 Directed
254
}
255
for (j in obj.servers6) {
248
- obj.servers6[j].send(wakeFunc.wakepacket, 0, wakeFunc.wakepacket.length, 16990, membershipIPv6);
256
+ obj.pendingOutboundPackets.push([obj.servers6[j], wakepacket, 16990, membershipIPv6]); // IPv6 Multicast
257
}
258
}
251
- func.wakepacket = wakepacket;
252
- func.host = host;
259
254
- // Call the wake function 3 times with small time intervals
255
- func();
256
- setTimeout(func, 200);
257
- setTimeout(func, 500);
260
+ // Send each packet at 10ms interval
261
+ // This packet spacing is absolutly required, otherwise the outbound buffer gets filled up and packets get lost which often causes the machine not to wake.
262
+ if (obj.pendingOutboundTimer == null) { obj.pendingOutboundTimer = setInterval(sendPendingPacket, 10); }
263
}
264
};
265