UNPKG

1.95 kBJavaScriptView Raw
1function spliceOne(list, index) {
2 for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
3 list[i] = list[k];
4 list.pop();
5}
6
7function Manager(interval, streamInterval, kaCountMax) {
8 var streams = this._streams = [];
9 this._timer = undefined;
10 this._timerInterval = interval;
11 this._timerfn = function() {
12 var now = Date.now();
13 for (var i = 0, len = streams.length, s, last; i < len; ++i) {
14 s = streams[i];
15 last = s._kalast;
16 if (last && (now - last) >= streamInterval) {
17 if (++s._kacnt > kaCountMax) {
18 var err = new Error('Keepalive timeout');
19 err.level = 'client-timeout';
20 s.emit('error', err);
21 s.disconnect();
22 spliceOne(streams, i);
23 --i;
24 len = streams.length;
25 } else {
26 s._kalast = now;
27 // XXX: if the server ever starts sending real global requests to the
28 // client, we will need to add a dummy callback here to keep the
29 // correct reply order
30 s.ping();
31 }
32 }
33 }
34 };
35}
36
37Manager.prototype.start = function() {
38 if (this._timer)
39 this.stop();
40 this._timer = setInterval(this._timerfn, this._timerInterval);
41};
42
43Manager.prototype.stop = function() {
44 if (this._timer) {
45 clearInterval(this._timer);
46 this._timer = undefined;
47 }
48};
49
50Manager.prototype.add = function(stream) {
51 var streams = this._streams,
52 self = this;
53
54 stream.once('end', function() {
55 self.remove(stream);
56 }).on('packet', resetKA);
57
58 streams[streams.length] = stream;
59
60 resetKA();
61
62 if (!this._timer)
63 this.start();
64
65 function resetKA() {
66 stream._kalast = Date.now();
67 stream._kacnt = 0;
68 }
69};
70
71Manager.prototype.remove = function(stream) {
72 var streams = this._streams,
73 index = streams.indexOf(stream);
74 if (index > -1)
75 spliceOne(streams, index);
76 if (!streams.length)
77 this.stop();
78};
79
80module.exports = Manager;