blob: a89bcd5200c355b92e08ff98e927a1a9840348c2 [file] [log] [blame]
Simon Hunta25cdcd2015-01-22 13:11:42 -08001#!/usr/bin/env node
Simon Hunta25cdcd2015-01-22 13:11:42 -08002
Simon Hunt711ee242015-01-22 15:08:02 -08003// === Mock Web Socket Server - for testing the topology view
4
5var fs = require('fs'),
6 readline = require('readline'),
7 http = require('http'),
8 WebSocketServer = require('websocket').server,
Simon Hunt74928302015-01-30 12:42:06 -08009 port = 8123,
10 scenarioRoot = 'ev/';
Simon Hunt711ee242015-01-22 15:08:02 -080011
12var lastcmd, // last command executed
13 lastargs, // arguments to last command
14 connection, // ws connection
15 origin, // origin of connection
Simon Hunt626d2102015-01-29 11:54:50 -080016 scid, // scenario ID
17 scdata, // scenario data
Simon Hunt711ee242015-01-22 15:08:02 -080018 scdone, // shows when scenario is over
Simon Hunt74928302015-01-30 12:42:06 -080019 eventsById, // map of event file names
20 maxEvno, // highest loaded event number
Simon Hunt711ee242015-01-22 15:08:02 -080021 evno, // next event number
22 evdata; // event data
23
24
Simon Hunt74928302015-01-30 12:42:06 -080025var scFiles = fs.readdirSync(scenarioRoot);
26console.log('Mock Server v1.0');
27console.log('================');
28console.log('Scenarios ...');
29console.log(scFiles.join(', '));
30console.log();
31
Simon Hunt711ee242015-01-22 15:08:02 -080032
33var rl = readline.createInterface(process.stdin, process.stdout);
34rl.setPrompt('ws> ');
Simon Hunta25cdcd2015-01-22 13:11:42 -080035
36
37var server = http.createServer(function(request, response) {
38 console.log((new Date()) + ' Received request for ' + request.url);
39 response.writeHead(404);
40 response.end();
41});
42
43server.listen(port, function() {
44 console.log((new Date()) + ' Server is listening on port ' + port);
45});
46
47server.on('listening', function () {
Simon Huntb0ec1e52015-01-28 18:13:49 -080048 console.log('OK, server is running');
Simon Hunt626d2102015-01-29 11:54:50 -080049 console.log('(? for help)');
Simon Hunta25cdcd2015-01-22 13:11:42 -080050});
51
52var wsServer = new WebSocketServer({
53 httpServer: server,
54 // You should not use autoAcceptConnections for production
55 // applications, as it defeats all standard cross-origin protection
56 // facilities built into the protocol and the browser. You should
57 // *always* verify the connection's origin and decide whether or not
58 // to accept it.
59 autoAcceptConnections: false
60});
61
62function originIsAllowed(origin) {
63 // put logic here to detect whether the specified origin is allowed.
64 return true;
65}
66
Simon Hunta25cdcd2015-01-22 13:11:42 -080067wsServer.on('request', function(request) {
68 console.log(); // newline after prompt
69 console.log("Origin: ", request.origin);
70
71 if (!originIsAllowed(request.origin)) {
72 // Make sure we only accept requests from an allowed origin
73 request.reject();
74 console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
75 return;
76 }
77
Simon Hunt711ee242015-01-22 15:08:02 -080078 origin = request.origin;
79 connection = request.accept(null, origin);
Simon Hunta25cdcd2015-01-22 13:11:42 -080080
81
82 console.log((new Date()) + ' Connection accepted.');
83 rl.prompt();
84
Simon Hunta25cdcd2015-01-22 13:11:42 -080085 connection.on('message', function(message) {
86 if (message.type === 'utf8') {
87 console.log(); // newline after prompt
88 console.log('Received Message: ' + message.utf8Data);
89 //connection.sendUTF(message.utf8Data);
90 rl.prompt();
91 }
92 else if (message.type === 'binary') {
93 console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
94 //connection.sendBytes(message.binaryData);
95 }
96 });
97 connection.on('close', function(reasonCode, description) {
98 console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
Simon Hunt711ee242015-01-22 15:08:02 -080099 connection = null;
100 origin = null;
Simon Hunta25cdcd2015-01-22 13:11:42 -0800101 });
102});
103
104
Simon Hunt711ee242015-01-22 15:08:02 -0800105setTimeout(doCli, 10); // allow async processes to write to stdout first
Simon Hunta25cdcd2015-01-22 13:11:42 -0800106
107function doCli() {
108 rl.prompt();
109 rl.on('line', function (line) {
110 var words = line.trim().split(' '),
Simon Hunt354c8c92015-01-22 15:32:51 -0800111 cmd = words.shift(),
112 str = words.join(' ');
113
114 if (!cmd) {
115 // repeat last command
116 cmd = lastcmd;
117 str = lastargs;
118 }
Simon Hunta25cdcd2015-01-22 13:11:42 -0800119
120 switch(cmd) {
Simon Hunt711ee242015-01-22 15:08:02 -0800121 case 'c': connStatus(); break;
122 case 'm': customMessage(str); break;
123 case 's': setScenario(str); break;
124 case 'n': nextEvent(); break;
Simon Huntb0ec1e52015-01-28 18:13:49 -0800125 case 'r': restartScenario(); break;
Simon Hunt711ee242015-01-22 15:08:02 -0800126 case 'q': quit(); break;
127 case '?': showHelp(); break;
128 default: console.log('Say what?! (? for help)'); break;
129 }
130 lastcmd = cmd;
131 lastargs = str;
132 rl.prompt();
Simon Hunta25cdcd2015-01-22 13:11:42 -0800133
Simon Hunt711ee242015-01-22 15:08:02 -0800134 }).on('close', function () {
135 quit();
136 });
137}
Simon Hunta25cdcd2015-01-22 13:11:42 -0800138
Simon Hunt711ee242015-01-22 15:08:02 -0800139var helptext = '\n' +
140 'c - show connection status\n' +
141 'm {text} - send custom message to client\n' +
Simon Huntb0ec1e52015-01-28 18:13:49 -0800142 's {id} - load scenario {id}\n' +
Simon Hunt711ee242015-01-22 15:08:02 -0800143 's - show scenario staus\n' +
144 //'a - auto-send events\n' +
145 'n - send next event\n' +
Simon Huntb0ec1e52015-01-28 18:13:49 -0800146 'r - restart the scenario\n' +
Simon Hunt711ee242015-01-22 15:08:02 -0800147 'q - exit the server\n' +
148 '? - display this help text\n';
Simon Hunta25cdcd2015-01-22 13:11:42 -0800149
Simon Hunt711ee242015-01-22 15:08:02 -0800150function showHelp() {
151 console.log(helptext);
152}
153
154function connStatus() {
155 if (connection) {
156 console.log('Connection from ' + origin + ' established.');
157 } else {
158 console.log('No connection.');
159 }
160}
161
162function quit() {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800163 console.log('Quitting...');
Simon Hunt711ee242015-01-22 15:08:02 -0800164 process.exit(0);
165}
166
167function customMessage(m) {
168 if (connection) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800169 console.log('Sending message: ' + m);
Simon Hunt711ee242015-01-22 15:08:02 -0800170 connection.sendUTF(m);
171 } else {
172 console.warn('No current connection.');
173 }
174}
175
176function showScenarioStatus() {
177 var msg;
Simon Hunt626d2102015-01-29 11:54:50 -0800178 if (!scid) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800179 console.log('No scenario loaded.');
Simon Hunt711ee242015-01-22 15:08:02 -0800180 } else {
Simon Hunt626d2102015-01-29 11:54:50 -0800181 msg = 'Scenario: "' + scid + '", ' +
Simon Hunt711ee242015-01-22 15:08:02 -0800182 (scdone ? 'DONE' : 'next event: ' + evno);
183 console.log(msg);
184 }
185}
186
187function scenarioPath(evno) {
Simon Hunt74928302015-01-30 12:42:06 -0800188 var file = evno ? ('/' + eventsById[evno].fname) : '/scenario.json';
189 return scenarioRoot + scid + file;
Simon Hunt626d2102015-01-29 11:54:50 -0800190}
191
192
193function initScenario(verb) {
194 console.log(); // get past prompt
195 console.log(verb + ' scenario "' + scid + '"');
196 console.log(scdata.title);
197 scdata.description.forEach(function (d) {
198 console.log(' ' + d);
199 });
200 evno = 1;
201 scdone = false;
Simon Hunt74928302015-01-30 12:42:06 -0800202 readEventFilenames();
203}
204
205function readEventFilenames() {
206 var files = fs.readdirSync(scenarioRoot + scid),
207 eventCount = 0,
208 match, id, tag;
209
210 maxEvno = 0;
211
212 eventsById = {};
213 files.forEach(function (f) {
214 match = /^ev_(\d+)_(.*)\.json$/.exec(f);
215 if (match) {
216 eventCount++;
217 id = match[1];
218 tag = match[2];
219 eventsById[id] = {
220 fname: f,
221 num: id,
222 tag: tag
223 };
224 if (Number(id) > Number(maxEvno)) {
225 maxEvno = id;
226 }
227 }
228
229 });
230 console.log('[' + eventCount + ' events loaded, (max=' + maxEvno + ')]');
Simon Hunt711ee242015-01-22 15:08:02 -0800231}
232
233function setScenario(id) {
234 if (!id) {
235 return showScenarioStatus();
236 }
237
238 evdata = null;
Simon Hunt626d2102015-01-29 11:54:50 -0800239 scid = id;
Simon Hunt711ee242015-01-22 15:08:02 -0800240 fs.readFile(scenarioPath(), 'utf8', function (err, data) {
241 if (err) {
242 console.warn('No scenario named "' + id + '"', err);
Simon Hunt626d2102015-01-29 11:54:50 -0800243 scid = null;
Simon Hunt711ee242015-01-22 15:08:02 -0800244 } else {
Simon Hunt626d2102015-01-29 11:54:50 -0800245 scdata = JSON.parse(data);
246 initScenario('Loading');
Simon Hunta25cdcd2015-01-22 13:11:42 -0800247 }
248 rl.prompt();
Simon Hunta25cdcd2015-01-22 13:11:42 -0800249 });
Simon Hunt711ee242015-01-22 15:08:02 -0800250}
Simon Hunta25cdcd2015-01-22 13:11:42 -0800251
Simon Huntb0ec1e52015-01-28 18:13:49 -0800252function restartScenario() {
Simon Hunt626d2102015-01-29 11:54:50 -0800253 if (!scid) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800254 console.log('No scenario loaded.');
255 } else {
Simon Hunt626d2102015-01-29 11:54:50 -0800256 initScenario('Restarting');
Simon Huntb0ec1e52015-01-28 18:13:49 -0800257 }
258 rl.prompt();
259}
260
Simon Hunt711ee242015-01-22 15:08:02 -0800261function nextEvent() {
262 var path;
263
Simon Hunt626d2102015-01-29 11:54:50 -0800264 if (!scid) {
Simon Huntb0ec1e52015-01-28 18:13:49 -0800265 console.log('No scenario loaded.');
Simon Hunt711ee242015-01-22 15:08:02 -0800266 rl.prompt();
267 } else if (!connection) {
268 console.warn('No current connection.');
269 rl.prompt();
270 } else {
Simon Hunt74928302015-01-30 12:42:06 -0800271 if (Number(evno) > Number(maxEvno)) {
272 // done
273 scdone = true;
274 console.log('Scenario DONE.');
275 } else {
276 // fire next event
277 path = scenarioPath(evno);
278 fs.readFile(path, 'utf8', function (err, data) {
279 if (err) {
280 console.log('Oops error: ' + err);
281 } else {
282 evdata = JSON.parse(data);
283 console.log(); // get past prompt
284 console.log('Sending event #' + evno + ' [' + evdata.event + ']');
285 connection.sendUTF(data);
286 evno++;
287 }
288 rl.prompt();
289 });
290 }
Simon Hunt711ee242015-01-22 15:08:02 -0800291 }
Simon Hunta25cdcd2015-01-22 13:11:42 -0800292}