blob: a5f1beb56625a89a3be7048e527c49666df57b1c [file] [log] [blame]
TamasBakai9b780332019-02-15 08:38:16 +00001var http = require('http');
2var https = require('https');
3
4var express = require('express');
5const stream = require('stream');
6var app = express();
7var fs = require("fs");
8var path = require('path');
BjornMagnussonXA42dcb262019-04-26 19:29:54 +00009const sleep = (milliseconds) => {
10 return new Promise(resolve => setTimeout(resolve, milliseconds))
11}
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000012var ArgumentParser = require('argparse').ArgumentParser;
TamasBakai9b780332019-02-15 08:38:16 +000013var privateKey = fs.readFileSync('cert/private.key', 'utf8');
14var certificate = fs.readFileSync('cert/certificate.crt', 'utf8');
15var credentials = {key: privateKey, cert: certificate};
16
BjornMagnussonXAa79a0432019-07-17 08:26:50 +000017var total_first_publish=0;
18var total_last_publish=0
19var total_files=0;
20var speed=0;
21
22var feeds="1:A"; //Comma separated list of feedId:filePrefix. Default is feedId=1 and file prefix 'A'
23var feedNames=[];
24var filePrefixes=[];
25var feedIndexes=[];
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000026
TamasBakai9b780332019-02-15 08:38:16 +000027var bodyParser = require('body-parser')
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000028var startTime = Date.now();
29
30var dr_callback_ip = '192.168.100.2'; //IP for DR when running as container. Can be changed by env DR_SIM_IP
31
32//Counters
BjornMagnussonXAa79a0432019-07-17 08:26:50 +000033var ctr_publish_requests = [];
34var ctr_publish_requests_bad_file_prefix = [];
35var ctr_publish_responses = [];
36var lastPublish = [];
37var dwl_volume = [];
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000038
39var parser = new ArgumentParser({
40 version: '0.0.1',
41 addHelp:true,
42 description: 'Datarouter redirect simulator'
43 });
44
45parser.addArgument('--tc' , { help: 'TC $NoOfTc' } );
46parser.addArgument('--printtc' ,
47 {
48 help: 'Print complete usage help',
49 action: 'storeTrue'
50 }
51 );
52
53var args = parser.parseArgs();
54const tc_normal = "normal";
55const tc_no_publish ="no_publish"
56const tc_10p_no_response = "10p_no_response";
57const tc_10first_no_response = "10first_no_response";
58const tc_100first_no_response = "100first_no_response";
BjornMagnussonXA42dcb262019-04-26 19:29:54 +000059const tc_all_delay_1s = "all_delay_1s";
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000060const tc_all_delay_10s = "all_delay_10s";
61const tc_10p_delay_10s = "10p_delay_10s";
62const tc_10p_error_response = "10p_error_response";
63const tc_10first_error_response = "10first_error_response";
64const tc_100first_error_response = "100first_error_response";
65
66if (args.tc==tc_normal) {
67 console.log("TC: " + args.tc)
68
69} else if (args.tc==tc_no_publish) {
70 console.log("TC: " + args.tc)
71
72} else if (args.tc==tc_10p_no_response) {
73 console.log("TC: " + args.tc)
74
75} else if (args.tc==tc_10first_no_response) {
76 console.log("TC: " + args.tc)
77
78} else if (args.tc==tc_100first_no_response) {
79 console.log("TC: " + args.tc)
80
BjornMagnussonXA42dcb262019-04-26 19:29:54 +000081} else if (args.tc==tc_all_delay_1s) {
82 console.log("TC: " + args.tc)
83
84 } else if (args.tc==tc_all_delay_10s) {
BjornMagnussonXAf4e18362019-04-10 13:04:08 +000085 console.log("TC: " + args.tc)
86
87} else if (args.tc==tc_10p_delay_10s) {
88 console.log("TC: " + args.tc)
89
90} else if (args.tc==tc_10p_error_response) {
91 console.log("TC: " + args.tc)
92
93} else if (args.tc==tc_10first_error_response) {
94 console.log("TC: " + args.tc)
95
96} else if (args.tc==tc_100first_error_response) {
97 console.log("TC: " + args.tc)
98} else {
99 console.log("No TC specified, use: --tc <tc-id>");
100 process.exit(0);
101}
102
103if (args.printtc) {
104 console.log("TC " + tc_normal + ": Normal case, all files publish and DR updated");
105 console.log("TC " + tc_no_publish + ": Ok response but no files published");
106 console.log("TC " + tc_10p_no_response + ": 10% % no response (file not published)");
107 console.log("TC " + tc_10first_no_response + ": 10 first requests give no response (files not published)");
108 console.log("TC " + tc_100first_no_response + ": 100 first requests give no response (files not published)");
BjornMagnussonXA42dcb262019-04-26 19:29:54 +0000109 console.log("TC " + tc_all_delay_1s + ": All responses delayed 1s, normal publish");
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000110 console.log("TC " + tc_all_delay_10s + ": All responses delayed 10s, normal publish");
111 console.log("TC " + tc_10p_delay_10s + ": 10% of responses delayed 10s, normal publish");
112 console.log("TC " + tc_10p_error_response + ": 10% error response (file not published)");
113 console.log("TC " + tc_10first_error_response + ": 10 first requests give error response (file not published)");
114 console.log("TC " + tc_100first_error_response + ": 100 first requests give error responses (file not published)");
115
116 process.exit(0);
117}
TamasBakai9b780332019-02-15 08:38:16 +0000118
119// parse application/x-www-form-urlencoded
120app.use(bodyParser.urlencoded({ extended: false }))
121
122// parse application/json
123app.use(bodyParser.json())
124
125// parse application/vnd.api+json as json
126app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
127
128// parse some custom thing into a Buffer
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000129app.use(bodyParser.raw({limit:1024*1024*60, type: 'application/octet-stream' }))
TamasBakai9b780332019-02-15 08:38:16 +0000130
131// parse an HTML body into a string
132app.use(bodyParser.text({ type: 'text/html' }))
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000133
134//Formatting
135function fmtMSS(s){
136 return(s-(s%=60))/60+(9<s?':':':0')+s //Format time diff to mm:ss
137}
138function fmtLargeNumber(x) {
139 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "); //Format large with space, eg: 1 000 000
140}
141
142//I'm alive function
TamasBakai9b780332019-02-15 08:38:16 +0000143app.get("/",function(req, res){
144 res.send("ok");
145})
146
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000147function toCommaList(ctrArray) {
148 var str="";
149 for(i=0;i<feedNames.length;i++) {
150 if (i!=0) {
151 str=str+",";
152 }
153 str=str+ctrArray[i];
154 }
155 return str;
156}
157
158function toCommaListTime(ctrArray) {
159 var str="";
160 for(i=0;i<feedNames.length;i++) {
161 if (i!=0) {
162 str=str+",";
163 }
164 if (ctrArray[i] < 0) {
165 str=str+"--:--";
166 } else {
167 str=str+fmtMSS(ctrArray[i]);
168 }
169 }
170 return str;
171}
172
173function sumList(ctrArray) {
174 var tmp=0;
175 for(i=0;i<feedNames.length;i++) {
176 tmp=tmp+ctrArray[i];
177 }
178 return ""+tmp;
179}
180
181function largestInListTime(ctrArray) {
182 var tmp=-1;
183 var str=""
184 for(i=0;i<feedNames.length;i++) {
185 if (ctrArray[i] > tmp) {
186 tmp = ctrArray[i];
187 }
188 }
189 if (tmp < 0) {
190 str="--:--";
191 } else {
192 str=fmtMSS(tmp);
193 }
194 return str;
195}
196
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000197//Counter readout
198app.get("/ctr_publish_requests",function(req, res){
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000199 res.send(""+sumList(ctr_publish_requests));
TamasBakai9b780332019-02-15 08:38:16 +0000200})
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000201app.get("/feeds/ctr_publish_requests/",function(req, res){
202 res.send(toCommaList(ctr_publish_requests));
203})
204app.get("/ctr_publish_requests/:feedId",function(req, res){
205 var feedId = req.params.feedId;
206 res.send(""+ctr_publish_requests[feedIndexes[feedId]]);
207})
208
209app.get("/ctr_publish_requests_bad_file_prefix",function(req, res){
210 res.send(""+sumList(ctr_publish_requests_bad_file_prefix));
211})
212app.get("/feeds/ctr_publish_requests_bad_file_prefix/",function(req, res){
213 res.send(toCommaList(ctr_publish_requests_bad_file_prefix));
214})
215app.get("/ctr_publish_requests_bad_file_prefix/:feedId",function(req, res){
216 var feedId = req.params.feedId;
217 res.send(""+ctr_publish_requests_bad_file_prefix[feedIndexes[feedId]]);
218})
219
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000220app.get("/ctr_publish_responses",function(req, res){
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000221 res.send(""+sumList(ctr_publish_responses));
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000222})
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000223app.get("/feeds/ctr_publish_responses/",function(req, res){
224 res.send(toCommaList(ctr_publish_responses));
225})
226app.get("/ctr_publish_responses/:feedId",function(req, res){
227 var feedId = req.params.feedId;
228 res.send(""+ctr_publish_responses[feedIndexes[feedId]]);
229})
230
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000231app.get("/execution_time",function(req, res){
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000232 var diff = fmtMSS(Math.floor((Date.now()-startTime)/1000));
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000233 res.send(""+diff);
234})
235app.get("/time_lastpublish",function(req, res){
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000236 res.send(""+largestInListTime(lastPublish));
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000237})
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000238app.get("/feeds/time_lastpublish/",function(req, res){
239 res.send(toCommaListTime(lastPublish));
240})
241app.get("/time_lastpublish/:feedId",function(req, res){
242 var feedId = req.params.feedId;
243 if (lastPublish[feedIndexes[feedId]] < 0) {
244 res.send("--:--");
245 }
246 res.send(""+fmtMSS(lastPublish[feedIndexes[feedId]]));
247})
248
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000249app.get("/dwl_volume",function(req, res){
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000250 res.send(""+fmtLargeNumber(sumList(dwl_volume)));
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000251})
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000252app.get("/feeds/dwl_volume/",function(req, res){
253 var str="";
254 for(i=0;i<feedNames.length;i++) {
255 if (i!=0) {
256 str=str+",";
257 }
258 str=str+fmtLargeNumber(dwl_volume[i]);
259 }
260 res.send(str);
261})
262app.get("/dwl_volume/:feedId",function(req, res){
263 var feedId = req.params.feedId;
264 res.send(""+fmtLargeNumber(dwl_volume[feedIndexes[feedId]]));
265})
266
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000267app.get("/tc_info",function(req, res){
268 res.send(args.tc);
269})
270
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000271app.get("/feeds",function(req, res){
272 res.send(feeds);
273})
274
275app.get("/speed",function(req, res){
276 res.send(""+speed);
277})
278
279function filenameStartsWith(fileName, feedIndex) {
280 var i=0;
281 for(i=0;i<filePrefixes[feedIndex].length;i++) {
282 var prefix=filePrefixes[feedIndex][i];
283 if (fileName.startsWith(prefix)) {
284 return true;
285 }
286 }
287 return false;
288}
289
290app.put('/publish/:feedId/:filename', function (req, res) {
291
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000292 console.log(req.url);
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000293 var feedId=req.params.feedId;
294// console.log("First 25 bytes of body: " + req.body.slice(0,25))
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000295 console.log(req.headers)
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000296 ctr_publish_requests[feedIndexes[feedId]]++;
297 var filename = req.params.filename;
298 if (!filenameStartsWith(filename, feedIndexes[feedId])) {
299 ctr_publish_requests_bad_file_prefix[feedIndexes[feedId]]++;
300 }
301 var ctr = ctr_publish_requests[feedIndexes[feedId]];
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000302 if (args.tc == tc_no_publish) {
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000303 ctr_publish_responses[feedIndexes[feedId]]++;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000304 res.send("ok")
305 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000306 } else if (args.tc==tc_10p_no_response && (ctr%10)==0) {
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000307 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000308 } else if (args.tc==tc_10first_no_response && ctr<11) {
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000309 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000310 } else if (args.tc==tc_100first_no_response && ctr<101) {
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000311 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000312 } else if (args.tc==tc_10p_error_response && (ctr%10)==0) {
313 ctr_publish_responses[feedIndexes[feedId]]++;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000314 res.send(400, "");
315 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000316 } else if (args.tc==tc_10first_error_response && ctr<11) {
317 ctr_publish_responses[feedIndexes[feedId]]++;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000318 res.send(400, "");
319 return;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000320 } else if (args.tc==tc_100first_error_response && ctr<101) {
321 ctr_publish_responses[feedIndexes[feedId]]++;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000322 res.send(400, "");
323 return;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000324 }
325
326 //Remaining part if normal file publish
327
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000328 console.log(filename);
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000329 //Create filename (appending file size and feedid to name) to store
330 var storedFilename = path.resolve(__dirname, filename+"-"+feedId+"-"+req.body.length);
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000331 fs.writeFile(storedFilename, "", function (error) { //Store file with zero size
332 if (error) { console.error(error); }
333 });
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000334
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000335 //Make callback to update list of publish files in DR sim
336 //Note the hard code ip-adress, DR sim get this ip if simulators started from the
337 //script in the 'simulatorgroup' dir.
338 //Work around: Could not get a normal http put to work from nodejs, using curl instead
339 var util = require('util');
340 var exec = require('child_process').exec;
341
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000342 var command = 'curl -s -X PUT http://' + dr_callback_ip + ':3906/dr_redir_publish/'+feedId+'/'+filename;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000343
344 console.log("Callback to DR sim to report file published, cmd: " + command);
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000345 var child = exec(command, function(error, stdout, stderr){
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000346 console.log('stdout: ' + stdout);
347 console.log('stderr: ' + stderr);
348 if(error !== null) {
349 console.log('exec error: ' + error);
350 }
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000351 });
352
353 //Update status variables
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000354 ctr_publish_responses[feedIndexes[feedId]]++;
355 lastPublish[feedIndexes[feedId]] = Math.floor((Date.now()-startTime)/1000);
356 dwl_volume[feedIndexes[feedId]] = dwl_volume[feedIndexes[feedId]] + req.body.length;
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000357
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000358 if (args.tc==tc_10p_delay_10s && (ctr%10)==0) {
BjornMagnussonXA42dcb262019-04-26 19:29:54 +0000359 sleep(10000).then(() => {
360 res.send("ok");
361 });
362 return;
363 } else if (args.tc==tc_all_delay_10s) {
364 sleep(10000).then(() => {
365 res.send("ok");
366 });
367 return;
368 } else if (args.tc==tc_all_delay_1s) {
369 sleep(1000).then(() => {
370 res.send("ok");
371 });
372 return;
373 }
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000374 if (total_first_publish == 0) {
375 total_first_publish=Date.now()/1000;
376 }
377 total_last_publish=Date.now()/1000;
378 total_files++;
379 if (total_last_publish > total_first_publish) {
380 speed = Math.round((total_files/(total_last_publish-total_first_publish))*10)/10;
381 }
382
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000383 res.send("ok")
384});
385
386
TamasBakai9b780332019-02-15 08:38:16 +0000387var httpServer = http.createServer(app);
388var httpsServer = https.createServer(credentials, app);
389
390var httpPort=3908
391var httpsPort=3909
392httpServer.listen(httpPort);
393console.log("DR-simulator listening (http) at "+httpPort)
394httpsServer.listen(httpsPort);
395console.log("DR-simulator listening (https) at "+httpsPort)
396
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000397if (process.env.DR_SIM_IP) {
398 dr_callback_ip=process.env.DR_SIM_IP;
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000399}
BjornMagnussonXAf4e18362019-04-10 13:04:08 +0000400console.log("Using IP " + dr_callback_ip + " for callback to DR sim");
BjornMagnussonXAa79a0432019-07-17 08:26:50 +0000401
402if (process.env.DR_REDIR_FEEDS) {
403 feeds=process.env.DR_REDIR_FEEDS;
404}
405console.log("Configured list of feeds: " + feeds);
406
407var i=0;
408feedNames=feeds.split(',');
409for(i=0;i<feedNames.length;i++) {
410 var tmp=feedNames[i].split(':');
411 feedNames[i]=tmp[0].trim();
412 feedIndexes[feedNames[i]]=i;
413 filePrefixes[i]=[]
414 var j=0;
415 for(j=1;j<tmp.length;j++) {
416 filePrefixes[i][j-1]=tmp[j];
417 }
418
419 ctr_publish_requests[i] = 0;
420 ctr_publish_requests_bad_file_prefix[i] = 0;
421 ctr_publish_responses[i] = 0;
422 lastPublish[i] = -1;
423 dwl_volume[i] = 0;
424}
425console.log("Parsed mapping between feed id and file name prefix");
426for(i=0;i<feedNames.length;i++) {
427 var fn = feedNames[i];
428 for (j=0;j<filePrefixes[i].length;j++) {
429 console.log("Feed id: " + fn + ", file name prefix: " + filePrefixes[i][j]);
430 }
431}