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