source: trip-planner-front/node_modules/websocket-extensions/lib/websocket_extensions.js@ 571e0df

Last change on this file since 571e0df was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.8 KB
Line 
1'use strict';
2
3var Parser = require('./parser'),
4 Pipeline = require('./pipeline');
5
6var Extensions = function() {
7 this._rsv1 = this._rsv2 = this._rsv3 = null;
8
9 this._byName = {};
10 this._inOrder = [];
11 this._sessions = [];
12 this._index = {};
13};
14
15Extensions.MESSAGE_OPCODES = [1, 2];
16
17var instance = {
18 add: function(ext) {
19 if (typeof ext.name !== 'string') throw new TypeError('extension.name must be a string');
20 if (ext.type !== 'permessage') throw new TypeError('extension.type must be "permessage"');
21
22 if (typeof ext.rsv1 !== 'boolean') throw new TypeError('extension.rsv1 must be true or false');
23 if (typeof ext.rsv2 !== 'boolean') throw new TypeError('extension.rsv2 must be true or false');
24 if (typeof ext.rsv3 !== 'boolean') throw new TypeError('extension.rsv3 must be true or false');
25
26 if (this._byName.hasOwnProperty(ext.name))
27 throw new TypeError('An extension with name "' + ext.name + '" is already registered');
28
29 this._byName[ext.name] = ext;
30 this._inOrder.push(ext);
31 },
32
33 generateOffer: function() {
34 var sessions = [],
35 offer = [],
36 index = {};
37
38 this._inOrder.forEach(function(ext) {
39 var session = ext.createClientSession();
40 if (!session) return;
41
42 var record = [ext, session];
43 sessions.push(record);
44 index[ext.name] = record;
45
46 var offers = session.generateOffer();
47 offers = offers ? [].concat(offers) : [];
48
49 offers.forEach(function(off) {
50 offer.push(Parser.serializeParams(ext.name, off));
51 }, this);
52 }, this);
53
54 this._sessions = sessions;
55 this._index = index;
56
57 return offer.length > 0 ? offer.join(', ') : null;
58 },
59
60 activate: function(header) {
61 var responses = Parser.parseHeader(header),
62 sessions = [];
63
64 responses.eachOffer(function(name, params) {
65 var record = this._index[name];
66
67 if (!record)
68 throw new Error('Server sent an extension response for unknown extension "' + name + '"');
69
70 var ext = record[0],
71 session = record[1],
72 reserved = this._reserved(ext);
73
74 if (reserved)
75 throw new Error('Server sent two extension responses that use the RSV' +
76 reserved[0] + ' bit: "' +
77 reserved[1] + '" and "' + ext.name + '"');
78
79 if (session.activate(params) !== true)
80 throw new Error('Server sent unacceptable extension parameters: ' +
81 Parser.serializeParams(name, params));
82
83 this._reserve(ext);
84 sessions.push(record);
85 }, this);
86
87 this._sessions = sessions;
88 this._pipeline = new Pipeline(sessions);
89 },
90
91 generateResponse: function(header) {
92 var sessions = [],
93 response = [],
94 offers = Parser.parseHeader(header);
95
96 this._inOrder.forEach(function(ext) {
97 var offer = offers.byName(ext.name);
98 if (offer.length === 0 || this._reserved(ext)) return;
99
100 var session = ext.createServerSession(offer);
101 if (!session) return;
102
103 this._reserve(ext);
104 sessions.push([ext, session]);
105 response.push(Parser.serializeParams(ext.name, session.generateResponse()));
106 }, this);
107
108 this._sessions = sessions;
109 this._pipeline = new Pipeline(sessions);
110
111 return response.length > 0 ? response.join(', ') : null;
112 },
113
114 validFrameRsv: function(frame) {
115 var allowed = { rsv1: false, rsv2: false, rsv3: false },
116 ext;
117
118 if (Extensions.MESSAGE_OPCODES.indexOf(frame.opcode) >= 0) {
119 for (var i = 0, n = this._sessions.length; i < n; i++) {
120 ext = this._sessions[i][0];
121 allowed.rsv1 = allowed.rsv1 || ext.rsv1;
122 allowed.rsv2 = allowed.rsv2 || ext.rsv2;
123 allowed.rsv3 = allowed.rsv3 || ext.rsv3;
124 }
125 }
126
127 return (allowed.rsv1 || !frame.rsv1) &&
128 (allowed.rsv2 || !frame.rsv2) &&
129 (allowed.rsv3 || !frame.rsv3);
130 },
131
132 processIncomingMessage: function(message, callback, context) {
133 this._pipeline.processIncomingMessage(message, callback, context);
134 },
135
136 processOutgoingMessage: function(message, callback, context) {
137 this._pipeline.processOutgoingMessage(message, callback, context);
138 },
139
140 close: function(callback, context) {
141 if (!this._pipeline) return callback.call(context);
142 this._pipeline.close(callback, context);
143 },
144
145 _reserve: function(ext) {
146 this._rsv1 = this._rsv1 || (ext.rsv1 && ext.name);
147 this._rsv2 = this._rsv2 || (ext.rsv2 && ext.name);
148 this._rsv3 = this._rsv3 || (ext.rsv3 && ext.name);
149 },
150
151 _reserved: function(ext) {
152 if (this._rsv1 && ext.rsv1) return [1, this._rsv1];
153 if (this._rsv2 && ext.rsv2) return [2, this._rsv2];
154 if (this._rsv3 && ext.rsv3) return [3, this._rsv3];
155 return false;
156 }
157};
158
159for (var key in instance)
160 Extensions.prototype[key] = instance[key];
161
162module.exports = Extensions;
Note: See TracBrowser for help on using the repository browser.