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