Matthias Nott
2026-03-07 0e888d62af1434fef231e11a5c307a5b48a8deb1
services/wol.ts
....@@ -56,12 +56,31 @@
5656 }
5757 }
5858
59
+ const TIMEOUT_MS = 5000;
60
+
5961 return new Promise<void>((resolve, reject) => {
62
+ let settled = false;
63
+ const settle = (fn: () => void) => {
64
+ if (settled) return;
65
+ settled = true;
66
+ clearTimeout(timer);
67
+ fn();
68
+ };
69
+
70
+ const timer = setTimeout(() => {
71
+ settle(() => {
72
+ try { socket.close(); } catch { /* ignore */ }
73
+ reject(new Error("WoL timed out — magic packet may not have been sent"));
74
+ });
75
+ }, TIMEOUT_MS);
76
+
6077 const socket = dgram.createSocket({ type: "udp4" });
6178
6279 socket.once("error", (err: Error) => {
63
- try { socket.close(); } catch { /* ignore */ }
64
- reject(err);
80
+ settle(() => {
81
+ try { socket.close(); } catch { /* ignore */ }
82
+ reject(err);
83
+ });
6584 });
6685
6786 socket.bind(0, () => {
....@@ -72,20 +91,22 @@
7291 }
7392
7493 let pending = broadcastAddresses.length;
75
- let failed = false;
7694
7795 for (const addr of broadcastAddresses) {
7896 socket.send(packet, 0, packet.length, 9, addr, (err?: Error) => {
79
- if (err && !failed) {
80
- failed = true;
81
- try { socket.close(); } catch { /* ignore */ }
82
- reject(err);
97
+ if (err) {
98
+ settle(() => {
99
+ try { socket.close(); } catch { /* ignore */ }
100
+ reject(err);
101
+ });
83102 return;
84103 }
85104 pending--;
86105 if (pending === 0) {
87
- try { socket.close(); } catch { /* ignore */ }
88
- resolve();
106
+ settle(() => {
107
+ try { socket.close(); } catch { /* ignore */ }
108
+ resolve();
109
+ });
89110 }
90111 });
91112 }