| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | 'use strict';var Buffer  = require('safe-buffer').Buffer,    Base    = require('./base'),    Draft75 = require('./draft75'),    crypto  = require('crypto'),    util    = require('util');var numberFromKey = function(key) {  return parseInt((key.match(/[0-9]/g) || []).join(''), 10);};var spacesInKey = function(key) {  return (key.match(/ /g) || []).length;};var Draft76 = function(request, url, options) {  Draft75.apply(this, arguments);  this._stage  = -1;  this._body   = [];  this.version = 'hixie-76';  this._headers.clear();  this._headers.set('Upgrade', 'WebSocket');  this._headers.set('Connection', 'Upgrade');  this._headers.set('Sec-WebSocket-Origin', this._request.headers.origin);  this._headers.set('Sec-WebSocket-Location', this.url);};util.inherits(Draft76, Draft75);var instance = {  BODY_SIZE: 8,  start: function() {    if (!Draft75.prototype.start.call(this)) return false;    this._started = true;    this._sendHandshakeBody();    return true;  },  close: function() {    if (this.readyState === 3) return false;    if (this.readyState === 1) this._write(Buffer.from([0xFF, 0x00]));    this.readyState = 3;    this.emit('close', new Base.CloseEvent(null, null));    return true;  },  _handshakeResponse: function() {    var headers = this._request.headers,        key1    = headers['sec-websocket-key1'],        key2    = headers['sec-websocket-key2'];    if (!key1) throw new Error('Missing required header: Sec-WebSocket-Key1');    if (!key2) throw new Error('Missing required header: Sec-WebSocket-Key2');    var number1 = numberFromKey(key1),        spaces1 = spacesInKey(key1),        number2 = numberFromKey(key2),        spaces2 = spacesInKey(key2);    if (number1 % spaces1 !== 0 || number2 % spaces2 !== 0)      throw new Error('Client sent invalid Sec-WebSocket-Key headers');    this._keyValues = [number1 / spaces1, number2 / spaces2];    var start   = 'HTTP/1.1 101 WebSocket Protocol Handshake',        headers = [start, this._headers.toString(), ''];    return Buffer.from(headers.join('\r\n'), 'binary');  },  _handshakeSignature: function() {    if (this._body.length < this.BODY_SIZE) return null;    var md5    = crypto.createHash('md5'),        buffer = Buffer.allocUnsafe(8 + this.BODY_SIZE);    buffer.writeUInt32BE(this._keyValues[0], 0);    buffer.writeUInt32BE(this._keyValues[1], 4);    Buffer.from(this._body).copy(buffer, 8, 0, this.BODY_SIZE);    md5.update(buffer);    return Buffer.from(md5.digest('binary'), 'binary');  },  _sendHandshakeBody: function() {    if (!this._started) return;    var signature = this._handshakeSignature();    if (!signature) return;    this._write(signature);    this._stage = 0;    this._open();    if (this._body.length > this.BODY_SIZE)      this.parse(this._body.slice(this.BODY_SIZE));  },  _parseLeadingByte: function(octet) {    if (octet !== 0xFF)      return Draft75.prototype._parseLeadingByte.call(this, octet);    this._closing = true;    this._length  = 0;    this._stage   = 1;  }};for (var key in instance)  Draft76.prototype[key] = instance[key];module.exports = Draft76;
 |