You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
2.4 KiB

7 years ago
  1. /**
  2. * Module dependencies.
  3. */
  4. var Transport = require('../transport');
  5. var parser = require('engine.io-parser');
  6. var util = require('util');
  7. var debug = require('debug')('engine:ws');
  8. /**
  9. * Export the constructor.
  10. */
  11. module.exports = WebSocket;
  12. /**
  13. * WebSocket transport
  14. *
  15. * @param {http.IncomingMessage}
  16. * @api public
  17. */
  18. function WebSocket (req) {
  19. Transport.call(this, req);
  20. var self = this;
  21. this.socket = req.websocket;
  22. this.socket.on('message', this.onData.bind(this));
  23. this.socket.once('close', this.onClose.bind(this));
  24. this.socket.on('error', this.onError.bind(this));
  25. this.socket.on('headers', onHeaders);
  26. this.writable = true;
  27. this.perMessageDeflate = null;
  28. function onHeaders (headers) {
  29. self.emit('headers', headers);
  30. }
  31. }
  32. /**
  33. * Inherits from Transport.
  34. */
  35. util.inherits(WebSocket, Transport);
  36. /**
  37. * Transport name
  38. *
  39. * @api public
  40. */
  41. WebSocket.prototype.name = 'websocket';
  42. /**
  43. * Advertise upgrade support.
  44. *
  45. * @api public
  46. */
  47. WebSocket.prototype.handlesUpgrades = true;
  48. /**
  49. * Advertise framing support.
  50. *
  51. * @api public
  52. */
  53. WebSocket.prototype.supportsFraming = true;
  54. /**
  55. * Processes the incoming data.
  56. *
  57. * @param {String} encoded packet
  58. * @api private
  59. */
  60. WebSocket.prototype.onData = function (data) {
  61. debug('received "%s"', data);
  62. Transport.prototype.onData.call(this, data);
  63. };
  64. /**
  65. * Writes a packet payload.
  66. *
  67. * @param {Array} packets
  68. * @api private
  69. */
  70. WebSocket.prototype.send = function (packets) {
  71. var self = this;
  72. for (var i = 0; i < packets.length; i++) {
  73. var packet = packets[i];
  74. parser.encodePacket(packet, self.supportsBinary, send);
  75. }
  76. function send (data) {
  77. debug('writing "%s"', data);
  78. // always creates a new object since ws modifies it
  79. var opts = {};
  80. if (packet.options) {
  81. opts.compress = packet.options.compress;
  82. }
  83. if (self.perMessageDeflate) {
  84. var len = 'string' === typeof data ? Buffer.byteLength(data) : data.length;
  85. if (len < self.perMessageDeflate.threshold) {
  86. opts.compress = false;
  87. }
  88. }
  89. self.writable = false;
  90. self.socket.send(data, opts, onEnd);
  91. }
  92. function onEnd (err) {
  93. if (err) return self.onError('write error', err.stack);
  94. self.writable = true;
  95. self.emit('drain');
  96. }
  97. };
  98. /**
  99. * Closes the transport.
  100. *
  101. * @api private
  102. */
  103. WebSocket.prototype.doClose = function (fn) {
  104. debug('closing');
  105. this.socket.close();
  106. fn && fn();
  107. };