-
Notifications
You must be signed in to change notification settings - Fork 5
/
DiagnosticsClient.js
211 lines (190 loc) · 7.23 KB
/
DiagnosticsClient.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*!
* NodePing
* Copyright(c) 2020 NodePing LLC
*/
/*!
* DiagnosticClient.js
* Websocket client to connect to NodePing diagnostic servers so you can run diagnostics on your AGENT.
*/
const WebSocket = require('ws');
var pingTimeout, ws;
var reconnectcount = 0;
var npconfig = require('./npconfig.json');
var config = require('./config.json');
var pingo = require('./diagnostics/ping.js');
var mtr = require('./diagnostics/mtr.js');
var traceroute = require('./diagnostics/traceroute.js');
var dig = require('./diagnostics/dig.js');
var ws;
var runningTool = 0;
if (!config.check_enabled) {
console.log(new Date().toISOString(),'Check is disabled in config.json - shutting down');
process.exit(0);
}
if (!npconfig.diagnosticserver || !npconfig.diagnosticserver.host || !npconfig.diagnosticserver.port) {
console.log(new Date().toISOString(),'Missing diagnosticserver info in npconfig.json - shutting down');
process.exit(0);
}
if (!config.check_id || !config.check_token || config.check_id === '<Your NodePing Check ID>' || config.check_token === '<Your NodePing Check Token>') {
console.log(new Date().toISOString(),'Missing check info in config.json - shutting down');
process.exit(0);
}
var heartbeat = function() {
console.log(new Date().toISOString(),'Heartbeat ping from the diagnostics server - responding with pong');
clearTimeout(pingTimeout);
pingTimeout = setTimeout( function(){
console.log(new Date().toISOString(),'Server timed out of heartbeat (31 seconds)');
ws.close();
reconnectcount++;
startClient();
}, 30000 + 1000);
};
var startClient = function() {
console.log(new Date().toISOString(),'Starting Client called - reconnectcount is',reconnectcount);
ws = false;
setTimeout(connectToServer,reconnectcount * 1000);
};
var connectToServer = function() {
console.log(new Date().toISOString(),'Connecting to server');
ws = new WebSocket('wss://'+npconfig.diagnosticserver.host+':'+npconfig.diagnosticserver.port+'/',{perMessageDeflate: false, timeout:4000});
ws.on('error', function error(err) {
console.log(new Date().toISOString(),'Error from server',err);
clearTimeout(pingTimeout);
ws.terminate();
});
ws.on('open', function open() {
reconnectcount = 0;
console.log(new Date().toISOString(),'connected');
heartbeat();
send({action:"register",agent:{checkid:config.check_id,checktoken:config.check_token}});
});
ws.on('close', function close() {
console.log(new Date().toISOString(),'disconnected');
clearTimeout(pingTimeout);
reconnectcount++;
startClient();
return true;
});
ws.on('message', function incoming(data) {
console.log(new Date().toISOString(),'Receiving request from diagnostics server');
processMessage(data);
});
ws.on('ping', heartbeat);
};
var send = function(payload, cb, retry) {
retry = retry || 0;
if (!cb) {
cb = function(){};
}
if (!ws || !ws.readyState) {
if (retry < 11) {
retry++;
return setTimeout(function() { return send(payload, cb, retry); }, 5000); // Wait 5 seconds for a reconnection.
} else {
console.log(new Date().toISOString(), 'No connection to diagnostic server after 1 minute. Discarding diagnostic:',payload);
return cb('No connection to diagnostic server after 1 minute. Discarding diagnostic.');
}
}
var payload = JSON.stringify(payload);
console.log(new Date().toISOString(),'Sending data to diagnostics server');
ws.send(payload, function() {
console.log(new Date().toISOString(),'Data sent');
return cb();
});
}
var parseData = function(data) {
try {
return JSON.parse(data);
} catch (parseerror) {
console.log(new Date().toISOString(),'Parse error', parseerror, data);
return {};
}
}
var processMessage = function (data) {
//console.log(new Date().toISOString(),'processing message',data);
var data = parseData(data);
//console.log(new Date().toISOString(),'processing parsed message',data);
if (data.shutdown) {
console.log(new Date().toISOString(),'Server is telling me to shutdown because:',data.message);
console.log(new Date().toISOString(),'Shutting down');
process.exit(0);
return false;
}
if (data.tool && tools.hasOwnProperty(data.tool)) {
console.log(new Date().toISOString(),'Going to run',data.tool,'on:',data);
runningTool++;
return tools[data.tool](data);
} else {
console.log(new Date().toISOString(),'Unknown test tool',data.tool,'for:',data);
data.error = 'Unknown test tool';
return send({action:'diagResults',data:data});
}
console.log(new Date().toISOString(),'Unknown message',data);
};
var tools = {
mtr: function(data) {
console.log(new Date().toISOString(),'Running mtr');
mtr.diagRun(data, function(reply) {
console.log(new Date().toISOString(),'mtr results:',reply);
data.results = reply;
send({action:'diagResults',data:data},function(){
runningTool--;
});
});
},
ping: function(data) {
console.log(new Date().toISOString(),'Running ping');
pingo.diagRun(data, function(reply) {
console.log(new Date().toISOString(),'ping results:',reply);
data.results = reply;
send({action:'diagResults',data:data},function(){
runningTool--;
});
});
},
traceroute: function(data) {
console.log(new Date().toISOString(),'Running traceroute');
traceroute.diagRun(data, function(reply) {
console.log(new Date().toISOString(),'traceroute results:',reply);
data.results = reply;
send({action:'diagResults',data:data},function(){
runningTool--;
});
});
},
dig: function(data) {
console.log(new Date().toISOString(),'Running dig');
dig.diagRun(data, function(reply) {
console.log(new Date().toISOString(),'dig results:',reply);
data.results = reply;
send({action:'diagResults',data:data},function(){
runningTool--;
});
});
}
};
var restartWSConnection = function(retry) {
retry = retry || 0;
if (retry > 10) {
console.log(new Date().toISOString(),'Restarting websocket connection after max retry');
ws.close();
} else {
if (runningTool) {
console.log(new Date().toISOString(),'Tool running - waiting to restart websocket connection.');
retry++;
setTimeout(function() {
restartWSConnection(retry);
},30000);
} else if (ws && typeof ws.close === 'function') {
console.log(new Date().toISOString(),'Restarting websocket connection');
ws.close();
} else {
console.log(new Date().toISOString(),'No websocket connection. Restarting the client.');
reconnectcount = 0;
startClient();
}
}
return true;
};
setInterval(restartWSConnection,3600000); // restart the websocket connection each hour.
startClient();