| 'use strict'; |
| |
| var Buffer = require('safe-buffer').Buffer, |
| Base = require('./base'), |
| util = require('util'); |
| |
| var Draft75 = function(request, url, options) { |
| Base.apply(this, arguments); |
| this._stage = 0; |
| this.version = 'hixie-75'; |
| |
| this._headers.set('Upgrade', 'WebSocket'); |
| this._headers.set('Connection', 'Upgrade'); |
| this._headers.set('WebSocket-Origin', this._request.headers.origin); |
| this._headers.set('WebSocket-Location', this.url); |
| }; |
| util.inherits(Draft75, Base); |
| |
| var instance = { |
| close: function() { |
| if (this.readyState === 3) return false; |
| this.readyState = 3; |
| this.emit('close', new Base.CloseEvent(null, null)); |
| return true; |
| }, |
| |
| parse: function(chunk) { |
| if (this.readyState > 1) return; |
| |
| this._reader.put(chunk); |
| |
| this._reader.eachByte(function(octet) { |
| var message; |
| |
| switch (this._stage) { |
| case -1: |
| this._body.push(octet); |
| this._sendHandshakeBody(); |
| break; |
| |
| case 0: |
| this._parseLeadingByte(octet); |
| break; |
| |
| case 1: |
| this._length = (octet & 0x7F) + 128 * this._length; |
| |
| if (this._closing && this._length === 0) { |
| return this.close(); |
| } |
| else if ((octet & 0x80) !== 0x80) { |
| if (this._length === 0) { |
| this._stage = 0; |
| } |
| else { |
| this._skipped = 0; |
| this._stage = 2; |
| } |
| } |
| break; |
| |
| case 2: |
| if (octet === 0xFF) { |
| this._stage = 0; |
| message = Buffer.from(this._buffer).toString('utf8', 0, this._buffer.length); |
| this.emit('message', new Base.MessageEvent(message)); |
| } |
| else { |
| if (this._length) { |
| this._skipped += 1; |
| if (this._skipped === this._length) |
| this._stage = 0; |
| } else { |
| this._buffer.push(octet); |
| if (this._buffer.length > this._maxLength) return this.close(); |
| } |
| } |
| break; |
| } |
| }, this); |
| }, |
| |
| frame: function(buffer) { |
| if (this.readyState === 0) return this._queue([buffer]); |
| if (this.readyState > 1) return false; |
| |
| if (typeof buffer !== 'string') buffer = buffer.toString(); |
| |
| var length = Buffer.byteLength(buffer), |
| frame = Buffer.allocUnsafe(length + 2); |
| |
| frame[0] = 0x00; |
| frame.write(buffer, 1); |
| frame[frame.length - 1] = 0xFF; |
| |
| this._write(frame); |
| return true; |
| }, |
| |
| _handshakeResponse: function() { |
| var start = 'HTTP/1.1 101 Web Socket Protocol Handshake', |
| headers = [start, this._headers.toString(), '']; |
| |
| return Buffer.from(headers.join('\r\n'), 'utf8'); |
| }, |
| |
| _parseLeadingByte: function(octet) { |
| if ((octet & 0x80) === 0x80) { |
| this._length = 0; |
| this._stage = 1; |
| } else { |
| delete this._length; |
| delete this._skipped; |
| this._buffer = []; |
| this._stage = 2; |
| } |
| } |
| }; |
| |
| for (var key in instance) |
| Draft75.prototype[key] = instance[key]; |
| |
| module.exports = Draft75; |