3 var Base = require('./base'),
4 Draft75 = require('./draft75'),
5 crypto = require('crypto'),
6 util = require('util');
9 var numberFromKey = function(key) {
10 return parseInt(key.match(/[0-9]/g).join(''), 10);
13 var spacesInKey = function(key) {
14 return key.match(/ /g).length;
18 var Draft76 = function(request, url, options) {
19 Draft75.apply(this, arguments);
22 this.version = 'hixie-76';
24 this._headers.clear();
26 this._headers.set('Upgrade', 'WebSocket');
27 this._headers.set('Connection', 'Upgrade');
28 this._headers.set('Sec-WebSocket-Origin', this._request.headers.origin);
29 this._headers.set('Sec-WebSocket-Location', this.url);
31 util.inherits(Draft76, Draft75);
37 if (!Draft75.prototype.start.call(this)) return false;
39 this._sendHandshakeBody();
44 if (this.readyState === 3) return false;
45 this._write(new Buffer([0xFF, 0x00]));
47 this.emit('close', new Base.CloseEvent(null, null));
51 _handshakeResponse: function() {
52 var headers = this._request.headers,
54 key1 = headers['sec-websocket-key1'],
55 number1 = numberFromKey(key1),
56 spaces1 = spacesInKey(key1),
58 key2 = headers['sec-websocket-key2'],
59 number2 = numberFromKey(key2),
60 spaces2 = spacesInKey(key2);
62 if (number1 % spaces1 !== 0 || number2 % spaces2 !== 0) {
63 this.emit('error', new Error('Client sent invalid Sec-WebSocket-Key headers'));
68 this._keyValues = [number1 / spaces1, number2 / spaces2];
70 var start = 'HTTP/1.1 101 WebSocket Protocol Handshake',
71 headers = [start, this._headers.toString(), ''];
73 return new Buffer(headers.join('\r\n'), 'binary');
76 _handshakeSignature: function() {
77 if (this._body.length < this.BODY_SIZE) return null;
79 var md5 = crypto.createHash('md5'),
80 buffer = new Buffer(8 + this.BODY_SIZE);
82 buffer.writeUInt32BE(this._keyValues[0], 0);
83 buffer.writeUInt32BE(this._keyValues[1], 4);
84 new Buffer(this._body).copy(buffer, 8, 0, this.BODY_SIZE);
87 return new Buffer(md5.digest('binary'), 'binary');
90 _sendHandshakeBody: function() {
91 if (!this._started) return;
92 var signature = this._handshakeSignature();
93 if (!signature) return;
95 this._write(signature);
99 if (this._body.length > this.BODY_SIZE)
100 this.parse(this._body.slice(this.BODY_SIZE));
103 _parseLeadingByte: function(octet) {
105 return Draft75.prototype._parseLeadingByte.call(this, octet);
107 this._closing = true;
113 for (var key in instance)
114 Draft76.prototype[key] = instance[key];
116 module.exports = Draft76;