@novnc/novnc 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +13 -0
- package/LICENSE.txt +2 -1
- package/README.md +69 -3
- package/core/base64.js +35 -41
- package/core/decoders/copyrect.js +22 -0
- package/core/decoders/hextile.js +137 -0
- package/core/decoders/raw.js +56 -0
- package/core/decoders/rre.js +44 -0
- package/core/decoders/tight.js +315 -0
- package/core/decoders/tightpng.js +27 -0
- package/core/deflator.js +85 -0
- package/core/des.js +90 -95
- package/core/display.js +254 -297
- package/core/encodings.js +7 -3
- package/core/inflator.js +48 -20
- package/core/input/domkeytable.js +21 -24
- package/core/input/fixedkeys.js +3 -1
- package/core/input/gesturehandler.js +567 -0
- package/core/input/keyboard.js +194 -120
- package/core/input/keysym.js +2 -0
- package/core/input/keysymdef.js +3 -3
- package/core/input/util.js +53 -12
- package/core/input/vkeys.js +2 -1
- package/core/rfb.js +1937 -1496
- package/core/util/browser.js +80 -29
- package/core/util/cursor.js +253 -0
- package/core/util/element.js +32 -0
- package/core/util/events.js +59 -55
- package/core/util/eventtarget.js +25 -30
- package/core/util/int.js +15 -0
- package/core/util/logging.js +21 -16
- package/core/util/polyfill.js +15 -8
- package/core/util/strings.js +21 -8
- package/core/websock.js +145 -167
- package/docs/API.md +31 -10
- package/lib/base64.js +115 -0
- package/lib/decoders/copyrect.js +44 -0
- package/lib/decoders/hextile.js +173 -0
- package/lib/decoders/raw.js +78 -0
- package/lib/decoders/rre.js +65 -0
- package/lib/decoders/tight.js +350 -0
- package/lib/decoders/tightpng.js +67 -0
- package/lib/deflator.js +99 -0
- package/lib/des.js +314 -0
- package/lib/display.js +733 -0
- package/lib/encodings.js +64 -0
- package/lib/inflator.js +87 -0
- package/lib/input/domkeytable.js +282 -0
- package/lib/input/fixedkeys.js +123 -0
- package/lib/input/gesturehandler.js +642 -0
- package/lib/input/keyboard.js +429 -0
- package/lib/input/keysym.js +1135 -0
- package/lib/input/keysymdef.js +1354 -0
- package/lib/input/util.js +304 -0
- package/lib/input/vkeys.js +127 -0
- package/lib/input/xtscancodes.js +505 -0
- package/lib/rfb.js +3448 -0
- package/lib/util/browser.js +131 -0
- package/lib/util/cursor.js +314 -0
- package/lib/util/element.js +43 -0
- package/lib/util/events.js +142 -0
- package/lib/util/eventtarget.js +64 -0
- package/lib/util/int.js +22 -0
- package/lib/util/logging.js +79 -0
- package/lib/util/polyfill.js +72 -0
- package/lib/util/strings.js +38 -0
- package/lib/vendor/pako/lib/utils/common.js +67 -0
- package/lib/vendor/pako/lib/zlib/adler32.js +33 -0
- package/lib/vendor/pako/lib/zlib/constants.js +51 -0
- package/lib/vendor/pako/lib/zlib/crc32.js +42 -0
- package/lib/vendor/pako/lib/zlib/deflate.js +2159 -0
- package/lib/vendor/pako/lib/zlib/gzheader.js +53 -0
- package/lib/vendor/pako/lib/zlib/inffast.js +445 -0
- package/lib/vendor/pako/lib/zlib/inflate.js +2114 -0
- package/lib/vendor/pako/lib/zlib/inftrees.js +418 -0
- package/lib/vendor/pako/lib/zlib/messages.js +36 -0
- package/lib/vendor/pako/lib/zlib/trees.js +1499 -0
- package/lib/vendor/pako/lib/zlib/zstream.js +46 -0
- package/lib/vendor/promise.js +255 -0
- package/lib/websock.js +374 -0
- package/package.json +48 -28
- package/vendor/pako/lib/zlib/deflate.js +30 -30
- package/vendor/pako/lib/zlib/inflate.js +17 -17
- package/core/input/mouse.js +0 -280
- package/docs/API-internal.md +0 -125
- package/docs/EMBEDDING.md +0 -83
- package/docs/VERSION +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = ZStream;
|
|
7
|
+
|
|
8
|
+
function ZStream() {
|
|
9
|
+
/* next input byte */
|
|
10
|
+
this.input = null; // JS specific, because we have no pointers
|
|
11
|
+
|
|
12
|
+
this.next_in = 0;
|
|
13
|
+
/* number of bytes available at input */
|
|
14
|
+
|
|
15
|
+
this.avail_in = 0;
|
|
16
|
+
/* total number of input bytes read so far */
|
|
17
|
+
|
|
18
|
+
this.total_in = 0;
|
|
19
|
+
/* next output byte should be put there */
|
|
20
|
+
|
|
21
|
+
this.output = null; // JS specific, because we have no pointers
|
|
22
|
+
|
|
23
|
+
this.next_out = 0;
|
|
24
|
+
/* remaining free space at output */
|
|
25
|
+
|
|
26
|
+
this.avail_out = 0;
|
|
27
|
+
/* total number of bytes output so far */
|
|
28
|
+
|
|
29
|
+
this.total_out = 0;
|
|
30
|
+
/* last error message, NULL if no error */
|
|
31
|
+
|
|
32
|
+
this.msg = ''
|
|
33
|
+
/*Z_NULL*/
|
|
34
|
+
;
|
|
35
|
+
/* not visible by applications */
|
|
36
|
+
|
|
37
|
+
this.state = null;
|
|
38
|
+
/* best guess about the data type: binary or text */
|
|
39
|
+
|
|
40
|
+
this.data_type = 2
|
|
41
|
+
/*Z_UNKNOWN*/
|
|
42
|
+
;
|
|
43
|
+
/* adler32 value of the uncompressed data */
|
|
44
|
+
|
|
45
|
+
this.adler = 0;
|
|
46
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/* Copyright (c) 2014 Taylor Hakes
|
|
2
|
+
* Copyright (c) 2014 Forbes Lindesay
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in
|
|
12
|
+
* all copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
+
* THE SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
(function (root) {
|
|
24
|
+
|
|
25
|
+
// Store setTimeout reference so promise-polyfill will be unaffected by
|
|
26
|
+
// other code modifying setTimeout (like sinon.useFakeTimers())
|
|
27
|
+
var setTimeoutFunc = setTimeout;
|
|
28
|
+
|
|
29
|
+
function noop() {}
|
|
30
|
+
|
|
31
|
+
// Polyfill for Function.prototype.bind
|
|
32
|
+
function bind(fn, thisArg) {
|
|
33
|
+
return function () {
|
|
34
|
+
fn.apply(thisArg, arguments);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Promise(fn) {
|
|
39
|
+
if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
|
|
40
|
+
if (typeof fn !== 'function') throw new TypeError('not a function');
|
|
41
|
+
this._state = 0;
|
|
42
|
+
this._handled = false;
|
|
43
|
+
this._value = undefined;
|
|
44
|
+
this._deferreds = [];
|
|
45
|
+
|
|
46
|
+
doResolve(fn, this);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function handle(self, deferred) {
|
|
50
|
+
while (self._state === 3) {
|
|
51
|
+
self = self._value;
|
|
52
|
+
}
|
|
53
|
+
if (self._state === 0) {
|
|
54
|
+
self._deferreds.push(deferred);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
self._handled = true;
|
|
58
|
+
Promise._immediateFn(function () {
|
|
59
|
+
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
|
|
60
|
+
if (cb === null) {
|
|
61
|
+
(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
var ret;
|
|
65
|
+
try {
|
|
66
|
+
ret = cb(self._value);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
reject(deferred.promise, e);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
resolve(deferred.promise, ret);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resolve(self, newValue) {
|
|
76
|
+
try {
|
|
77
|
+
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
|
78
|
+
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
|
|
79
|
+
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
|
|
80
|
+
var then = newValue.then;
|
|
81
|
+
if (newValue instanceof Promise) {
|
|
82
|
+
self._state = 3;
|
|
83
|
+
self._value = newValue;
|
|
84
|
+
finale(self);
|
|
85
|
+
return;
|
|
86
|
+
} else if (typeof then === 'function') {
|
|
87
|
+
doResolve(bind(then, newValue), self);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
self._state = 1;
|
|
92
|
+
self._value = newValue;
|
|
93
|
+
finale(self);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
reject(self, e);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function reject(self, newValue) {
|
|
100
|
+
self._state = 2;
|
|
101
|
+
self._value = newValue;
|
|
102
|
+
finale(self);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function finale(self) {
|
|
106
|
+
if (self._state === 2 && self._deferreds.length === 0) {
|
|
107
|
+
Promise._immediateFn(function() {
|
|
108
|
+
if (!self._handled) {
|
|
109
|
+
Promise._unhandledRejectionFn(self._value);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (var i = 0, len = self._deferreds.length; i < len; i++) {
|
|
115
|
+
handle(self, self._deferreds[i]);
|
|
116
|
+
}
|
|
117
|
+
self._deferreds = null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function Handler(onFulfilled, onRejected, promise) {
|
|
121
|
+
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
|
122
|
+
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
|
123
|
+
this.promise = promise;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Take a potentially misbehaving resolver function and make sure
|
|
128
|
+
* onFulfilled and onRejected are only called once.
|
|
129
|
+
*
|
|
130
|
+
* Makes no guarantees about asynchrony.
|
|
131
|
+
*/
|
|
132
|
+
function doResolve(fn, self) {
|
|
133
|
+
var done = false;
|
|
134
|
+
try {
|
|
135
|
+
fn(function (value) {
|
|
136
|
+
if (done) return;
|
|
137
|
+
done = true;
|
|
138
|
+
resolve(self, value);
|
|
139
|
+
}, function (reason) {
|
|
140
|
+
if (done) return;
|
|
141
|
+
done = true;
|
|
142
|
+
reject(self, reason);
|
|
143
|
+
});
|
|
144
|
+
} catch (ex) {
|
|
145
|
+
if (done) return;
|
|
146
|
+
done = true;
|
|
147
|
+
reject(self, ex);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Promise.prototype['catch'] = function (onRejected) {
|
|
152
|
+
return this.then(null, onRejected);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
Promise.prototype.then = function (onFulfilled, onRejected) {
|
|
156
|
+
var prom = new (this.constructor)(noop);
|
|
157
|
+
|
|
158
|
+
handle(this, new Handler(onFulfilled, onRejected, prom));
|
|
159
|
+
return prom;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
Promise.all = function (arr) {
|
|
163
|
+
var args = Array.prototype.slice.call(arr);
|
|
164
|
+
|
|
165
|
+
return new Promise(function (resolve, reject) {
|
|
166
|
+
if (args.length === 0) return resolve([]);
|
|
167
|
+
var remaining = args.length;
|
|
168
|
+
|
|
169
|
+
function res(i, val) {
|
|
170
|
+
try {
|
|
171
|
+
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
|
172
|
+
var then = val.then;
|
|
173
|
+
if (typeof then === 'function') {
|
|
174
|
+
then.call(val, function (val) {
|
|
175
|
+
res(i, val);
|
|
176
|
+
}, reject);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
args[i] = val;
|
|
181
|
+
if (--remaining === 0) {
|
|
182
|
+
resolve(args);
|
|
183
|
+
}
|
|
184
|
+
} catch (ex) {
|
|
185
|
+
reject(ex);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (var i = 0; i < args.length; i++) {
|
|
190
|
+
res(i, args[i]);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
Promise.resolve = function (value) {
|
|
196
|
+
if (value && typeof value === 'object' && value.constructor === Promise) {
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return new Promise(function (resolve) {
|
|
201
|
+
resolve(value);
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
Promise.reject = function (value) {
|
|
206
|
+
return new Promise(function (resolve, reject) {
|
|
207
|
+
reject(value);
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
Promise.race = function (values) {
|
|
212
|
+
return new Promise(function (resolve, reject) {
|
|
213
|
+
for (var i = 0, len = values.length; i < len; i++) {
|
|
214
|
+
values[i].then(resolve, reject);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Use polyfill for setImmediate for performance gains
|
|
220
|
+
Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
|
|
221
|
+
function (fn) {
|
|
222
|
+
setTimeoutFunc(fn, 0);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
|
|
226
|
+
if (typeof console !== 'undefined' && console) {
|
|
227
|
+
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Set the immediate function to execute callbacks
|
|
233
|
+
* @param fn {function} Function to execute
|
|
234
|
+
* @deprecated
|
|
235
|
+
*/
|
|
236
|
+
Promise._setImmediateFn = function _setImmediateFn(fn) {
|
|
237
|
+
Promise._immediateFn = fn;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Change the function to execute on unhandled rejection
|
|
242
|
+
* @param {function} fn Function to execute on unhandled rejection
|
|
243
|
+
* @deprecated
|
|
244
|
+
*/
|
|
245
|
+
Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
|
|
246
|
+
Promise._unhandledRejectionFn = fn;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
250
|
+
module.exports = Promise;
|
|
251
|
+
} else if (!root.Promise) {
|
|
252
|
+
root.Promise = Promise;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
})(this);
|
package/lib/websock.js
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var Log = _interopRequireWildcard(require("./util/logging.js"));
|
|
11
|
+
|
|
12
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
|
|
13
|
+
|
|
14
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
15
|
+
|
|
16
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
17
|
+
|
|
18
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
19
|
+
|
|
20
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
21
|
+
|
|
22
|
+
// this has performance issues in some versions Chromium, and
|
|
23
|
+
// doesn't gain a tremendous amount of performance increase in Firefox
|
|
24
|
+
// at the moment. It may be valuable to turn it on in the future.
|
|
25
|
+
// Also copyWithin() for TypedArrays is not supported in IE 11 or
|
|
26
|
+
// Safari 13 (at the moment we want to support Safari 11).
|
|
27
|
+
var ENABLE_COPYWITHIN = false;
|
|
28
|
+
var MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
|
|
29
|
+
|
|
30
|
+
var Websock = /*#__PURE__*/function () {
|
|
31
|
+
function Websock() {
|
|
32
|
+
_classCallCheck(this, Websock);
|
|
33
|
+
|
|
34
|
+
this._websocket = null; // WebSocket object
|
|
35
|
+
|
|
36
|
+
this._rQi = 0; // Receive queue index
|
|
37
|
+
|
|
38
|
+
this._rQlen = 0; // Next write position in the receive queue
|
|
39
|
+
|
|
40
|
+
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
|
|
41
|
+
// called in init: this._rQ = new Uint8Array(this._rQbufferSize);
|
|
42
|
+
|
|
43
|
+
this._rQ = null; // Receive queue
|
|
44
|
+
|
|
45
|
+
this._sQbufferSize = 1024 * 10; // 10 KiB
|
|
46
|
+
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
|
|
47
|
+
|
|
48
|
+
this._sQlen = 0;
|
|
49
|
+
this._sQ = null; // Send queue
|
|
50
|
+
|
|
51
|
+
this._eventHandlers = {
|
|
52
|
+
message: function message() {},
|
|
53
|
+
open: function open() {},
|
|
54
|
+
close: function close() {},
|
|
55
|
+
error: function error() {}
|
|
56
|
+
};
|
|
57
|
+
} // Getters and Setters
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
_createClass(Websock, [{
|
|
61
|
+
key: "rQpeek8",
|
|
62
|
+
value: function rQpeek8() {
|
|
63
|
+
return this._rQ[this._rQi];
|
|
64
|
+
}
|
|
65
|
+
}, {
|
|
66
|
+
key: "rQskipBytes",
|
|
67
|
+
value: function rQskipBytes(bytes) {
|
|
68
|
+
this._rQi += bytes;
|
|
69
|
+
}
|
|
70
|
+
}, {
|
|
71
|
+
key: "rQshift8",
|
|
72
|
+
value: function rQshift8() {
|
|
73
|
+
return this._rQshift(1);
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
key: "rQshift16",
|
|
77
|
+
value: function rQshift16() {
|
|
78
|
+
return this._rQshift(2);
|
|
79
|
+
}
|
|
80
|
+
}, {
|
|
81
|
+
key: "rQshift32",
|
|
82
|
+
value: function rQshift32() {
|
|
83
|
+
return this._rQshift(4);
|
|
84
|
+
} // TODO(directxman12): test performance with these vs a DataView
|
|
85
|
+
|
|
86
|
+
}, {
|
|
87
|
+
key: "_rQshift",
|
|
88
|
+
value: function _rQshift(bytes) {
|
|
89
|
+
var res = 0;
|
|
90
|
+
|
|
91
|
+
for (var byte = bytes - 1; byte >= 0; byte--) {
|
|
92
|
+
res += this._rQ[this._rQi++] << byte * 8;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return res;
|
|
96
|
+
}
|
|
97
|
+
}, {
|
|
98
|
+
key: "rQshiftStr",
|
|
99
|
+
value: function rQshiftStr(len) {
|
|
100
|
+
if (typeof len === 'undefined') {
|
|
101
|
+
len = this.rQlen;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var str = ""; // Handle large arrays in steps to avoid long strings on the stack
|
|
105
|
+
|
|
106
|
+
for (var i = 0; i < len; i += 4096) {
|
|
107
|
+
var part = this.rQshiftBytes(Math.min(4096, len - i));
|
|
108
|
+
str += String.fromCharCode.apply(null, part);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return str;
|
|
112
|
+
}
|
|
113
|
+
}, {
|
|
114
|
+
key: "rQshiftBytes",
|
|
115
|
+
value: function rQshiftBytes(len) {
|
|
116
|
+
if (typeof len === 'undefined') {
|
|
117
|
+
len = this.rQlen;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this._rQi += len;
|
|
121
|
+
return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
|
|
122
|
+
}
|
|
123
|
+
}, {
|
|
124
|
+
key: "rQshiftTo",
|
|
125
|
+
value: function rQshiftTo(target, len) {
|
|
126
|
+
if (len === undefined) {
|
|
127
|
+
len = this.rQlen;
|
|
128
|
+
} // TODO: make this just use set with views when using a ArrayBuffer to store the rQ
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
|
|
132
|
+
this._rQi += len;
|
|
133
|
+
}
|
|
134
|
+
}, {
|
|
135
|
+
key: "rQslice",
|
|
136
|
+
value: function rQslice(start) {
|
|
137
|
+
var end = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.rQlen;
|
|
138
|
+
return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
|
|
139
|
+
} // Check to see if we must wait for 'num' bytes (default to FBU.bytes)
|
|
140
|
+
// to be available in the receive queue. Return true if we need to
|
|
141
|
+
// wait (and possibly print a debug message), otherwise false.
|
|
142
|
+
|
|
143
|
+
}, {
|
|
144
|
+
key: "rQwait",
|
|
145
|
+
value: function rQwait(msg, num, goback) {
|
|
146
|
+
if (this.rQlen < num) {
|
|
147
|
+
if (goback) {
|
|
148
|
+
if (this._rQi < goback) {
|
|
149
|
+
throw new Error("rQwait cannot backup " + goback + " bytes");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this._rQi -= goback;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return true; // true means need more data
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return false;
|
|
159
|
+
} // Send Queue
|
|
160
|
+
|
|
161
|
+
}, {
|
|
162
|
+
key: "flush",
|
|
163
|
+
value: function flush() {
|
|
164
|
+
if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
|
|
165
|
+
this._websocket.send(this._encodeMessage());
|
|
166
|
+
|
|
167
|
+
this._sQlen = 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}, {
|
|
171
|
+
key: "send",
|
|
172
|
+
value: function send(arr) {
|
|
173
|
+
this._sQ.set(arr, this._sQlen);
|
|
174
|
+
|
|
175
|
+
this._sQlen += arr.length;
|
|
176
|
+
this.flush();
|
|
177
|
+
}
|
|
178
|
+
}, {
|
|
179
|
+
key: "sendString",
|
|
180
|
+
value: function sendString(str) {
|
|
181
|
+
this.send(str.split('').map(function (chr) {
|
|
182
|
+
return chr.charCodeAt(0);
|
|
183
|
+
}));
|
|
184
|
+
} // Event Handlers
|
|
185
|
+
|
|
186
|
+
}, {
|
|
187
|
+
key: "off",
|
|
188
|
+
value: function off(evt) {
|
|
189
|
+
this._eventHandlers[evt] = function () {};
|
|
190
|
+
}
|
|
191
|
+
}, {
|
|
192
|
+
key: "on",
|
|
193
|
+
value: function on(evt, handler) {
|
|
194
|
+
this._eventHandlers[evt] = handler;
|
|
195
|
+
}
|
|
196
|
+
}, {
|
|
197
|
+
key: "_allocateBuffers",
|
|
198
|
+
value: function _allocateBuffers() {
|
|
199
|
+
this._rQ = new Uint8Array(this._rQbufferSize);
|
|
200
|
+
this._sQ = new Uint8Array(this._sQbufferSize);
|
|
201
|
+
}
|
|
202
|
+
}, {
|
|
203
|
+
key: "init",
|
|
204
|
+
value: function init() {
|
|
205
|
+
this._allocateBuffers();
|
|
206
|
+
|
|
207
|
+
this._rQi = 0;
|
|
208
|
+
this._websocket = null;
|
|
209
|
+
}
|
|
210
|
+
}, {
|
|
211
|
+
key: "open",
|
|
212
|
+
value: function open(uri, protocols) {
|
|
213
|
+
var _this = this;
|
|
214
|
+
|
|
215
|
+
this.init();
|
|
216
|
+
this._websocket = new WebSocket(uri, protocols);
|
|
217
|
+
this._websocket.binaryType = 'arraybuffer';
|
|
218
|
+
this._websocket.onmessage = this._recvMessage.bind(this);
|
|
219
|
+
|
|
220
|
+
this._websocket.onopen = function () {
|
|
221
|
+
Log.Debug('>> WebSock.onopen');
|
|
222
|
+
|
|
223
|
+
if (_this._websocket.protocol) {
|
|
224
|
+
Log.Info("Server choose sub-protocol: " + _this._websocket.protocol);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
_this._eventHandlers.open();
|
|
228
|
+
|
|
229
|
+
Log.Debug("<< WebSock.onopen");
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
this._websocket.onclose = function (e) {
|
|
233
|
+
Log.Debug(">> WebSock.onclose");
|
|
234
|
+
|
|
235
|
+
_this._eventHandlers.close(e);
|
|
236
|
+
|
|
237
|
+
Log.Debug("<< WebSock.onclose");
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
this._websocket.onerror = function (e) {
|
|
241
|
+
Log.Debug(">> WebSock.onerror: " + e);
|
|
242
|
+
|
|
243
|
+
_this._eventHandlers.error(e);
|
|
244
|
+
|
|
245
|
+
Log.Debug("<< WebSock.onerror: " + e);
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}, {
|
|
249
|
+
key: "close",
|
|
250
|
+
value: function close() {
|
|
251
|
+
if (this._websocket) {
|
|
252
|
+
if (this._websocket.readyState === WebSocket.OPEN || this._websocket.readyState === WebSocket.CONNECTING) {
|
|
253
|
+
Log.Info("Closing WebSocket connection");
|
|
254
|
+
|
|
255
|
+
this._websocket.close();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this._websocket.onmessage = function () {};
|
|
259
|
+
}
|
|
260
|
+
} // private methods
|
|
261
|
+
|
|
262
|
+
}, {
|
|
263
|
+
key: "_encodeMessage",
|
|
264
|
+
value: function _encodeMessage() {
|
|
265
|
+
// Put in a binary arraybuffer
|
|
266
|
+
// according to the spec, you can send ArrayBufferViews with the send method
|
|
267
|
+
return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
|
|
268
|
+
} // We want to move all the unread data to the start of the queue,
|
|
269
|
+
// e.g. compacting.
|
|
270
|
+
// The function also expands the receive que if needed, and for
|
|
271
|
+
// performance reasons we combine these two actions to avoid
|
|
272
|
+
// unneccessary copying.
|
|
273
|
+
|
|
274
|
+
}, {
|
|
275
|
+
key: "_expandCompactRQ",
|
|
276
|
+
value: function _expandCompactRQ(minFit) {
|
|
277
|
+
// if we're using less than 1/8th of the buffer even with the incoming bytes, compact in place
|
|
278
|
+
// instead of resizing
|
|
279
|
+
var requiredBufferSize = (this._rQlen - this._rQi + minFit) * 8;
|
|
280
|
+
var resizeNeeded = this._rQbufferSize < requiredBufferSize;
|
|
281
|
+
|
|
282
|
+
if (resizeNeeded) {
|
|
283
|
+
// Make sure we always *at least* double the buffer size, and have at least space for 8x
|
|
284
|
+
// the current amount of data
|
|
285
|
+
this._rQbufferSize = Math.max(this._rQbufferSize * 2, requiredBufferSize);
|
|
286
|
+
} // we don't want to grow unboundedly
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
if (this._rQbufferSize > MAX_RQ_GROW_SIZE) {
|
|
290
|
+
this._rQbufferSize = MAX_RQ_GROW_SIZE;
|
|
291
|
+
|
|
292
|
+
if (this._rQbufferSize - this.rQlen < minFit) {
|
|
293
|
+
throw new Error("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (resizeNeeded) {
|
|
298
|
+
var oldRQbuffer = this._rQ.buffer;
|
|
299
|
+
this._rQ = new Uint8Array(this._rQbufferSize);
|
|
300
|
+
|
|
301
|
+
this._rQ.set(new Uint8Array(oldRQbuffer, this._rQi, this._rQlen - this._rQi));
|
|
302
|
+
} else {
|
|
303
|
+
if (ENABLE_COPYWITHIN) {
|
|
304
|
+
this._rQ.copyWithin(0, this._rQi, this._rQlen);
|
|
305
|
+
} else {
|
|
306
|
+
this._rQ.set(new Uint8Array(this._rQ.buffer, this._rQi, this._rQlen - this._rQi));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
this._rQlen = this._rQlen - this._rQi;
|
|
311
|
+
this._rQi = 0;
|
|
312
|
+
} // push arraybuffer values onto the end of the receive que
|
|
313
|
+
|
|
314
|
+
}, {
|
|
315
|
+
key: "_DecodeMessage",
|
|
316
|
+
value: function _DecodeMessage(data) {
|
|
317
|
+
var u8 = new Uint8Array(data);
|
|
318
|
+
|
|
319
|
+
if (u8.length > this._rQbufferSize - this._rQlen) {
|
|
320
|
+
this._expandCompactRQ(u8.length);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
this._rQ.set(u8, this._rQlen);
|
|
324
|
+
|
|
325
|
+
this._rQlen += u8.length;
|
|
326
|
+
}
|
|
327
|
+
}, {
|
|
328
|
+
key: "_recvMessage",
|
|
329
|
+
value: function _recvMessage(e) {
|
|
330
|
+
this._DecodeMessage(e.data);
|
|
331
|
+
|
|
332
|
+
if (this.rQlen > 0) {
|
|
333
|
+
this._eventHandlers.message();
|
|
334
|
+
|
|
335
|
+
if (this._rQlen == this._rQi) {
|
|
336
|
+
// All data has now been processed, this means we
|
|
337
|
+
// can reset the receive queue.
|
|
338
|
+
this._rQlen = 0;
|
|
339
|
+
this._rQi = 0;
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
Log.Debug("Ignoring empty message");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}, {
|
|
346
|
+
key: "sQ",
|
|
347
|
+
get: function get() {
|
|
348
|
+
return this._sQ;
|
|
349
|
+
}
|
|
350
|
+
}, {
|
|
351
|
+
key: "rQ",
|
|
352
|
+
get: function get() {
|
|
353
|
+
return this._rQ;
|
|
354
|
+
}
|
|
355
|
+
}, {
|
|
356
|
+
key: "rQi",
|
|
357
|
+
get: function get() {
|
|
358
|
+
return this._rQi;
|
|
359
|
+
},
|
|
360
|
+
set: function set(val) {
|
|
361
|
+
this._rQi = val;
|
|
362
|
+
} // Receive Queue
|
|
363
|
+
|
|
364
|
+
}, {
|
|
365
|
+
key: "rQlen",
|
|
366
|
+
get: function get() {
|
|
367
|
+
return this._rQlen - this._rQi;
|
|
368
|
+
}
|
|
369
|
+
}]);
|
|
370
|
+
|
|
371
|
+
return Websock;
|
|
372
|
+
}();
|
|
373
|
+
|
|
374
|
+
exports.default = Websock;
|