-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
80 lines (68 loc) · 2.08 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
'use strict'
const os = require('os')
const net = require('net')
const dgram = require('dgram')
let createWOLPacket = mac => {
mac = mac.replace(/:/g, '')
if (mac.length !== 12 || mac.match(/[^a-fA-F0-9]/)) throw new Error(`Invalid MAC address: ${mac}`)
return new Buffer('ff'.repeat(6) + mac.repeat(16), 'hex')
}
let getBroadcastAddr = (ip, netmask) => {
let a = ip.split('.').map(s => parseInt(s, 10))
let b = netmask.split('.').map(s => parseInt(s, 10))
let c = []
for (let i = 0; i < a.length; i++) c.push((a[i] & b[i]) | (b[i] ^ 255))
return c.join('.')
}
let sendToAll = (mac, opts) => {
let promises = []
let ifaces = os.networkInterfaces()
for (let p in ifaces) {
ifaces[p].forEach(iface => {
if (iface.internal || !net.isIPv4(iface.address)) return
let ifaceOpts = Object.assign({}, opts)
ifaceOpts.from = iface.address
ifaceOpts.address = getBroadcastAddr(iface.address, iface.netmask)
promises.push(send(mac, ifaceOpts))
})
}
return Promise.all(promises)
}
let send = (mac, opts = {}) => {
if (!opts.from) return sendToAll(mac, opts)
return new Promise((resolve, reject) => {
try {
let from = opts.from
let port = opts.port || 9
let count = opts.count || 3
let address = opts.address || '255.255.255.255'
let interval = opts.interval || 100
let intervalId
let pkt = createWOLPacket(mac)
let done = err => {
count--
if (!count || err) {
socket.close()
clearInterval(intervalId)
if (err) return reject(err)
return resolve()
}
}
let doSend = () => {
socket.send(pkt, 0, pkt.length, port, address, done)
}
let socket = dgram.createSocket(net.isIPv6(address) ? 'udp6' : 'udp4')
socket.unref()
socket.bind(0, from, err => {
if (err) return reject(err)
socket.setBroadcast(true)
socket.once('error', done)
doSend()
intervalId = setInterval(doSend, interval)
})
} catch (err) {
return reject(err)
}
})
}
module.exports = send