index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * Dependencies
  3. */
  4. var delegate = require('delegates');
  5. var net = require('net');
  6. /**
  7. * Socket v2
  8. */
  9. function Socket (options) {
  10. this.socket = new net.Socket(options);
  11. this.monitor();
  12. }
  13. /**
  14. * Socket prototype
  15. */
  16. var socket = Socket.prototype;
  17. /**
  18. * Remember connection arguments for reconnection
  19. */
  20. socket.connect = function () {
  21. this._connectArgs = arguments;
  22. return this.socket.connect.apply(this.socket, arguments);
  23. };
  24. /**
  25. * Stop monitoring
  26. */
  27. socket.destroy = function () {
  28. clearTimeout(this._connectTimeout);
  29. this.socket.removeAllListeners();
  30. return this.socket.destroy();
  31. };
  32. /**
  33. * Reconnect on close
  34. */
  35. socket.monitor = function () {
  36. var self = this;
  37. var backoff = 1.5;
  38. var delay = 1000;
  39. this.socket.on('connect', function () {
  40. clearTimeout(this._connectTimeout);
  41. delay = 1000;
  42. });
  43. this.socket.on('close', function () {
  44. this._connectTimeout = setTimeout(function () {
  45. self._reconnect();
  46. }, delay);
  47. });
  48. this.socket.on('error', function (err) {
  49. if (err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET') {
  50. return this._connectTimout = setTimeout(function () {
  51. self._reconnect();
  52. }, delay);
  53. delay *= backoff;
  54. };
  55. throw err;
  56. });
  57. };
  58. socket._reconnect = function () {
  59. if (this.socket._connecting) return;
  60. this.socket.connect.apply(this.socket, this._connectArgs);
  61. };
  62. /**
  63. * Proxy net.Socket methods and properties
  64. */
  65. var methods = [
  66. // net.Socket
  67. 'setEncoding',
  68. 'write',
  69. 'end',
  70. 'pause',
  71. 'resume',
  72. 'setTimeout',
  73. 'setNoDelay',
  74. 'setKeepAlive',
  75. 'address',
  76. 'unref',
  77. 'ref',
  78. // EventEmitter
  79. 'addListener',
  80. 'on',
  81. 'once',
  82. 'removeListener',
  83. 'removeAllListeners',
  84. 'setMaxListeners',
  85. 'listeners',
  86. 'emit'
  87. ];
  88. var properties = [
  89. // net.Socket
  90. 'bufferSize',
  91. 'remoteAddress',
  92. 'remoteFamily',
  93. 'remotePort',
  94. 'localAddress',
  95. 'localPort',
  96. 'bytesRead',
  97. 'bytesWritten',
  98. // EventEmitter
  99. 'defaultMaxListeners',
  100. ];
  101. methods.forEach(function (method) {
  102. socket[method] = function () {
  103. return this.socket[method].apply(this.socket, arguments);
  104. };
  105. });
  106. properties.forEach(function (property) {
  107. delegate(socket, 'socket').access(property);
  108. });
  109. /**
  110. * Expose connect method
  111. */
  112. exports.connect = exports.createConnection = function (port, host, connectionListener) {
  113. var options = {};
  114. if (typeof port === 'object') options = port;
  115. if (typeof port === 'string') options.path = port;
  116. if (typeof port === 'number') options.port = port;
  117. if (typeof host === 'function') connectionListener = host;
  118. if (typeof host === 'string') options.host = host;
  119. var socket = new Socket();
  120. socket.connect(options, connectionListener);
  121. return socket;
  122. };