| '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; |