]> git.wh0rd.org - chrome-ext/wake-on-lan.git/blob - js/main.js
bfe3530bb3c144464b6b818ddb998404a92af6b4
[chrome-ext/wake-on-lan.git] / js / main.js
1 // Written by Mike Frysinger <vapier@gmail.com>.
2 // Released into the public domain.
3
4 function status(msg) {
5 $$('[name=status]').innerText = msg;
6 }
7
8 // Create a packet following the spec:
9 // https://en.wikipedia.org/wiki/Wake-on-LAN#Magic_packet
10 function magicpacket(mac, pass) {
11 var data = new ArrayBuffer(6 + 16 * 6 + 6 + 6);
12 var bytes = new Uint8Array(data);
13 var i, j, base = 0;
14
15 // First 6 bytes should be all 0xFF.
16 for (i = 0; i < 6; ++i)
17 bytes[base + i] = 0xff;
18 base += 6;
19
20 // Then the MAC address is repeated 16 times.
21 for (i = 0; i < 6; ++i)
22 for (j = 0; j < 16 * 6; j += 6)
23 bytes[base + j + i] = mac[i];
24 base += 16 * 6;
25
26 // Then 6 bytes before the pass should be 0xFF.
27 for (i = 0; i < 6; ++i)
28 bytes[base + i] = 0xff;
29 base += 6;
30
31 // Finally the 6 bytes of the password.
32 for (i = 0; i < 6; ++i)
33 bytes[base + i] = pass[i];
34
35 return data;
36 }
37
38 function split_data(v) {
39 var data = Array(6);
40 var i, idata;
41
42 window['sync_' + v]();
43
44 for (i = 0; i < 6; ++i) {
45 idata = $$('input[name=' + v + i + ']');
46 if (!/^[0-9a-fA-F]?[0-9a-fA-F]$/.test(idata.value.replace(' ', ''))) {
47 status(v + ' byte ' + i + ' is invalid; must be 2 hex characters');
48 idata.focus();
49 idata.setSelectionRange(0, idata.value.length);
50 return false;
51 }
52 data[i] = parseInt(idata.value, 16);
53 }
54
55 return data;
56 }
57
58 function send() {
59 status('initializing');
60
61 var form = $$('form[name=settings]');
62 var shost = '0.0.0.0';
63 var dhost = form.host.value;
64 var port = parseInt(form.port.value);
65
66 // Get the MAC address & password to convert to packet data.
67 var mac = split_data('mac');
68 var pass = split_data('pass');
69 var data = magicpacket(mac, pass);
70 console.log('packet', new Uint8Array(data));
71
72 var checkresult = function(s, step, result) {
73 if (result < 0) {
74 status('error in ' + step + ': ' + net_error_list[result]);
75 chrome.sockets.udp.close(s, nullcb);
76 return false;
77 }
78 return true;
79 };
80
81 // Create the socket ...
82 chrome.sockets.udp.create({}, function(createInfo) {
83 var s = createInfo.socketId;
84
85 console.log('[create] socketInfo', createInfo);
86 status('binding ' + shost);
87
88 // Bind it locally ...
89 chrome.sockets.udp.bind(s, shost, 0, function(result) {
90 console.log('[bind] result', result);
91
92 if (!checkresult(s, 'bind', result))
93 return false;
94
95 status('enabling broadcast');
96
97 // Turn on broadcast support ...
98 chrome.sockets.udp.setBroadcast(s, true, function(result) {
99 console.log('[setBroadcast] result', result);
100
101 if (!checkresult(s, 'broadcast', result))
102 return false;
103
104 status('sending to ' + dhost + ':' + port);
105
106 // Send the backet ...
107 chrome.sockets.udp.send(s, data, dhost, port, function(sendInfo) {
108 console.log('[send] sendInfo', sendInfo);
109
110 if (!checkresult(s, 'send', sendInfo.resultCode))
111 return false;
112
113 status('closing');
114
115 // Shut it down ...
116 chrome.sockets.udp.close(s, function() {
117 status('sent to ' + dhost + ':' + port);
118 store_settings();
119 });
120 });
121 });
122 });
123 });
124
125 // Keep the form from submitting.
126 return false;
127 }
128
129 function sync_it(v) {
130 var smany = $$('span[name=' + v + '-many]');
131 var sone = $$('span[name=' + v + '-one]');
132
133 // Sync the two sets of fields.
134 var i;
135 if (smany.hidden) {
136 var idata = $$('input[name=' + v + ']');
137 var data = idata.value.split(':');
138
139 if (data.length != 6) {
140 data = idata.value.replace(/[ :]/g, '');
141 if (data.length != 6 * 2) {
142 status('invalid ' + v + '; please fix');
143 return false;
144 }
145 data = data.match(/../g);
146 } else {
147 for (i = 0; i < 6; ++i)
148 if (data[i].length > 2) {
149 status('invalid ' + v + ' please fix');
150 return false;
151 }
152 }
153
154 for (i = 0; i < 6; ++i)
155 $$('input[name=' + v + i + ']').value = data[i];
156 } else {
157 var data = '';
158
159 for (i = 0; i < 6; ++i) {
160 data += $$('input[name=' + v + i + ']').value;
161 if (i < 5)
162 data += ':';
163 }
164
165 $$('input[name=' + v + ']').value = data;
166 }
167 }
168 function sync_mac() { return sync_it('mac'); }
169 function sync_pass() { return sync_it('pass'); }
170
171
172 function paste_mac() {
173 sync_mac();
174
175 var smany = $$('span[name=mac-many]');
176 var sone = $$('span[name=mac-one]');
177 smany.hidden = !smany.hidden;
178 sone.hidden = !sone.hidden;
179
180 return false;
181 }
182
183 function paste_pass() {
184 sync_pass();
185
186 var smany = $$('span[name=pass-many]');
187 var sone = $$('span[name=pass-one]');
188 smany.hidden = !smany.hidden;
189 sone.hidden = !sone.hidden;
190
191 return false;
192 }
193
194 /*
195 * Storage logic.
196 */
197 var settings_keys = [
198 'host',
199 'mac',
200 'pass',
201 'port',
202 'theme',
203 ];
204
205 var default_theme = 'dark';
206 var default_host = '192.168.0.255';
207 var default_port = '40000';
208 var default_mac = '20:00:00:00:00:00';
209 var default_pass = '00:00:00:00:00:00';
210
211 function load_settings() {
212 var storage = chrome.storage.local;
213
214 chrome.storage.local.get(settings_keys, function(settings) {
215 set_theme(settings['theme'] || default_theme);
216 var form = $$('form[name=settings]');
217 form.host.value = settings['host'] || default_host;
218 form.port.value = settings['port'] || default_port;
219 // We assume we only get called during init.
220 paste_mac();
221 form.mac.value = settings['mac'] || default_mac;
222 paste_mac();
223 paste_pass();
224 form.pass.value = settings['pass'] || default_pass;
225 paste_pass();
226 });
227 }
228
229 function store_settings() {
230 var form = $$('form[name=settings]');
231 sync_mac();
232 sync_pass();
233 var settings = {
234 'host': form.host.value,
235 'mac': form.mac.value,
236 'pass': form.pass.value,
237 'port': form.port.value,
238 'theme': curr_theme,
239 };
240 chrome.storage.local.set(settings);
241 }
242
243 /*
244 * Startup.
245 */
246 window.onload = function() {
247 $$('form[name=settings]').onsubmit = send;
248 $$('a[name=mac-paste]').onclick = paste_mac;
249 $$('a[name=pass-paste]').onclick = paste_pass;
250 $$('input[name=theme]').onclick = toggle_theme;
251
252 load_settings();
253 };