keepalivemgr.js 1.9 KB

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