first
This commit is contained in:
162
node_modules/websocket-extensions/lib/websocket_extensions.js
generated
vendored
Normal file
162
node_modules/websocket-extensions/lib/websocket_extensions.js
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
'use strict';
|
||||
|
||||
var Parser = require('./parser'),
|
||||
Pipeline = require('./pipeline');
|
||||
|
||||
var Extensions = function() {
|
||||
this._rsv1 = this._rsv2 = this._rsv3 = null;
|
||||
|
||||
this._byName = {};
|
||||
this._inOrder = [];
|
||||
this._sessions = [];
|
||||
this._index = {};
|
||||
};
|
||||
|
||||
Extensions.MESSAGE_OPCODES = [1, 2];
|
||||
|
||||
var instance = {
|
||||
add: function(ext) {
|
||||
if (typeof ext.name !== 'string') throw new TypeError('extension.name must be a string');
|
||||
if (ext.type !== 'permessage') throw new TypeError('extension.type must be "permessage"');
|
||||
|
||||
if (typeof ext.rsv1 !== 'boolean') throw new TypeError('extension.rsv1 must be true or false');
|
||||
if (typeof ext.rsv2 !== 'boolean') throw new TypeError('extension.rsv2 must be true or false');
|
||||
if (typeof ext.rsv3 !== 'boolean') throw new TypeError('extension.rsv3 must be true or false');
|
||||
|
||||
if (this._byName.hasOwnProperty(ext.name))
|
||||
throw new TypeError('An extension with name "' + ext.name + '" is already registered');
|
||||
|
||||
this._byName[ext.name] = ext;
|
||||
this._inOrder.push(ext);
|
||||
},
|
||||
|
||||
generateOffer: function() {
|
||||
var sessions = [],
|
||||
offer = [],
|
||||
index = {};
|
||||
|
||||
this._inOrder.forEach(function(ext) {
|
||||
var session = ext.createClientSession();
|
||||
if (!session) return;
|
||||
|
||||
var record = [ext, session];
|
||||
sessions.push(record);
|
||||
index[ext.name] = record;
|
||||
|
||||
var offers = session.generateOffer();
|
||||
offers = offers ? [].concat(offers) : [];
|
||||
|
||||
offers.forEach(function(off) {
|
||||
offer.push(Parser.serializeParams(ext.name, off));
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
this._sessions = sessions;
|
||||
this._index = index;
|
||||
|
||||
return offer.length > 0 ? offer.join(', ') : null;
|
||||
},
|
||||
|
||||
activate: function(header) {
|
||||
var responses = Parser.parseHeader(header),
|
||||
sessions = [];
|
||||
|
||||
responses.eachOffer(function(name, params) {
|
||||
var record = this._index[name];
|
||||
|
||||
if (!record)
|
||||
throw new Error('Server sent an extension response for unknown extension "' + name + '"');
|
||||
|
||||
var ext = record[0],
|
||||
session = record[1],
|
||||
reserved = this._reserved(ext);
|
||||
|
||||
if (reserved)
|
||||
throw new Error('Server sent two extension responses that use the RSV' +
|
||||
reserved[0] + ' bit: "' +
|
||||
reserved[1] + '" and "' + ext.name + '"');
|
||||
|
||||
if (session.activate(params) !== true)
|
||||
throw new Error('Server sent unacceptable extension parameters: ' +
|
||||
Parser.serializeParams(name, params));
|
||||
|
||||
this._reserve(ext);
|
||||
sessions.push(record);
|
||||
}, this);
|
||||
|
||||
this._sessions = sessions;
|
||||
this._pipeline = new Pipeline(sessions);
|
||||
},
|
||||
|
||||
generateResponse: function(header) {
|
||||
var sessions = [],
|
||||
response = [],
|
||||
offers = Parser.parseHeader(header);
|
||||
|
||||
this._inOrder.forEach(function(ext) {
|
||||
var offer = offers.byName(ext.name);
|
||||
if (offer.length === 0 || this._reserved(ext)) return;
|
||||
|
||||
var session = ext.createServerSession(offer);
|
||||
if (!session) return;
|
||||
|
||||
this._reserve(ext);
|
||||
sessions.push([ext, session]);
|
||||
response.push(Parser.serializeParams(ext.name, session.generateResponse()));
|
||||
}, this);
|
||||
|
||||
this._sessions = sessions;
|
||||
this._pipeline = new Pipeline(sessions);
|
||||
|
||||
return response.length > 0 ? response.join(', ') : null;
|
||||
},
|
||||
|
||||
validFrameRsv: function(frame) {
|
||||
var allowed = { rsv1: false, rsv2: false, rsv3: false },
|
||||
ext;
|
||||
|
||||
if (Extensions.MESSAGE_OPCODES.indexOf(frame.opcode) >= 0) {
|
||||
for (var i = 0, n = this._sessions.length; i < n; i++) {
|
||||
ext = this._sessions[i][0];
|
||||
allowed.rsv1 = allowed.rsv1 || ext.rsv1;
|
||||
allowed.rsv2 = allowed.rsv2 || ext.rsv2;
|
||||
allowed.rsv3 = allowed.rsv3 || ext.rsv3;
|
||||
}
|
||||
}
|
||||
|
||||
return (allowed.rsv1 || !frame.rsv1) &&
|
||||
(allowed.rsv2 || !frame.rsv2) &&
|
||||
(allowed.rsv3 || !frame.rsv3);
|
||||
},
|
||||
|
||||
processIncomingMessage: function(message, callback, context) {
|
||||
this._pipeline.processIncomingMessage(message, callback, context);
|
||||
},
|
||||
|
||||
processOutgoingMessage: function(message, callback, context) {
|
||||
this._pipeline.processOutgoingMessage(message, callback, context);
|
||||
},
|
||||
|
||||
close: function(callback, context) {
|
||||
if (!this._pipeline) return callback.call(context);
|
||||
this._pipeline.close(callback, context);
|
||||
},
|
||||
|
||||
_reserve: function(ext) {
|
||||
this._rsv1 = this._rsv1 || (ext.rsv1 && ext.name);
|
||||
this._rsv2 = this._rsv2 || (ext.rsv2 && ext.name);
|
||||
this._rsv3 = this._rsv3 || (ext.rsv3 && ext.name);
|
||||
},
|
||||
|
||||
_reserved: function(ext) {
|
||||
if (this._rsv1 && ext.rsv1) return [1, this._rsv1];
|
||||
if (this._rsv2 && ext.rsv2) return [2, this._rsv2];
|
||||
if (this._rsv3 && ext.rsv3) return [3, this._rsv3];
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
for (var key in instance)
|
||||
Extensions.prototype[key] = instance[key];
|
||||
|
||||
module.exports = Extensions;
|
Reference in New Issue
Block a user