124 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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;
 |