-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
123 lines (99 loc) · 3.13 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
var dgram = require('dgram'),
dns = require('dns'),
net = require('net'),
Buffer = require('buffer').Buffer,
chalk = require('chalk'),
vow = require('vow');
const BROADCAST = '255.255.255.255';
module.exports = function(mac, params) {
getIP(params).then(function(ip) {
var magicPacket = createMagicPacket(mac);
if (params.relay) {
relay(mac, ip, magicPacket, params);
} else {
send(mac, ip, magicPacket, params);
}
});
}
function send(mac, ip, magicPacket, params) {
var socket = dgram.createSocket(net.isIPv6(ip) ? 'udp6' : 'udp4');
socket.once('listening', function() {
socket.setBroadcast(ip === BROADCAST)
});
if (ip === BROADCAST) {
console.log('Broadcasting magic packet to %s.', chalk.blue(mac));
} else {
console.log('Sending magic packet to %s with IP=%s.', chalk.blue(mac), chalk.magenta(ip));
}
socket.send(magicPacket, 0, magicPacket.length, params.port, ip, function(err) {
if (err) {
console.log(chalk.red('Sorry ;('));
console.error(err);
} else {
console.log('%s. Your computer is awakening right now...', chalk.green('All\'s fine'));
}
socket.close();
});
}
function relay(mac, ip, magicPacket, params) {
socket = dgram.createSocket('udp4');
socket.on('error', (err) => {
console.log(`Server error:\n${err.stack}`);
socket.close();
});
socket.on('message', (msg, rinfo) => {
if (msg.equals(magicPacket)) {
send(mac, ip, magicPacket, params);
}
});
socket.on('listening', () => {
const address = socket.address();
console.log(`Server listening ${address.address}:${address.port}`);
});
socket.bind(params.relayport);
}
const MAC_BYTES = 6;
const MAC_REPETITIONS = 16;
/**
* Magic packet is:
* FF (repeat 6)
* MAC Address (repeat 16)
*/
function createMagicPacket(mac) {
var macBuffer = new Buffer(MAC_BYTES);
mac.split(':').forEach(function(value, i) {
macBuffer[i] = parseInt(value, 16);
});
var buffer = new Buffer(MAC_BYTES + MAC_REPETITIONS * MAC_BYTES);
// start the magic packet from 6 bytes of FF
for (var i = 0; i < MAC_BYTES; i++) {
buffer[i] = 0xFF;
}
// copy mac address 16 times
for (var i = 0; i < MAC_REPETITIONS; i++) {
macBuffer.copy(buffer, (i + 1) * MAC_BYTES, 0, macBuffer.length);
}
return buffer;
}
function getIP(params) {
var defer = vow.defer();
if (!params.host) {
defer.resolve(params.ip);
} else {
dns.resolve(params.host, function(err, addresses) {
if (err) {
console.error(err);
defer.resolve(BROADCAST)
} else {
defer.resolve(addresses[0]);
}
});
}
return defer.promise();
}
module.exports.isMACValid = function(mac) {
if (mac.length == 2 * MAC_BYTES + (MAC_BYTES - 1)) {
mac = mac.replace(new RegExp(mac[2], 'g'), '');
}
return !(mac.length != 2 * MAC_BYTES || mac.match(/[^a-fA-F0-9]/));
}