Skip to content

Commit

Permalink
Use Typed Arrays for the Websock receive queue
Browse files Browse the repository at this point in the history
**This commit removes Base64 (and Flash) support**

This commit converts websock.js to used Typed Arrays for the
receive queue (and tweaks rfb.js to ensure that it continues
to function, since only Firefox implements
`%TypedArray%.prototype.slice`).  Base64 support was removed
to simplify code paths, and pave the way for using Typed Arrays
for the send queue as well.

This provides two advantages: first, we allocate a buffer ahead
of time, meaning the browser doesn't have to do any work dynamically
increasing the receive queue size.  Secondly, we are now able to pass
around Typed Array Views (e.g. `Uint8Array`), which are lightweight, and
don't involve copying.

The downside is that we initially allocate more memory -- we currently
start out with 4 MiB, and then automatically double when it looks like
the amount unused is getting to small.

The commit also explicitly adds a check to the compacting logic that
avoids calling the copy functions if `_rQlen === _rQi`.
  • Loading branch information
DirectXMan12 committed Aug 6, 2015
1 parent 6c88365 commit 38781d9
Show file tree
Hide file tree
Showing 15 changed files with 240 additions and 713 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "include/web-socket-js-project"]
path = include/web-socket-js-project
url = https://github.com/gimite/web-socket-js.git
3 changes: 0 additions & 3 deletions LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ licenses (all MPL 2.0 compatible):

include/jsunzip.js : zlib/libpng license

include/web-socket-js/ : New BSD license (3-clause). Source code at
http://github.com/gimite/web-socket-js

include/chrome-app/tcp-stream.js
: Apache 2.0 license

Expand Down
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,7 @@ See more screenshots <a href="http://kanaka.github.com/noVNC/screenshots.html">h
* HTML5 Canvas (with createImageData): Chrome, Firefox 3.6+, iOS
Safari, Opera 11+, Internet Explorer 9+, etc.

* HTML5 WebSockets: For browsers that do not have builtin
WebSockets support, the project includes
<a href="http://github.com/gimite/web-socket-js">web-socket-js</a>,
a WebSockets emulator using Adobe Flash. iOS 4.2+ has built-in
WebSocket support.
* HTML5 WebSockets and Typed Arrays

* Fast Javascript Engine: this is not strictly a requirement, but
without a fast Javascript engine, noVNC might be painfully slow.
Expand Down Expand Up @@ -130,7 +126,6 @@ use a WebSockets to TCP socket proxy. There is a python proxy included
* tight encoding : Michael Tinglof (Mercuri.ca)

* Included libraries:
* web-socket-js : Hiroshi Ichikawa (github.com/gimite/web-socket-js)
* as3crypto : Henri Torgemane (code.google.com/p/as3crypto)
* base64 : Martijn Pieters (Digital Creations 2), Samuel Sieb (sieb.net)
* DES : Dave Zimmerman (Widget Workshop), Jef Poskanzer (ACME Labs)
Expand Down
18 changes: 0 additions & 18 deletions docs/notes
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
Some implementation notes:

There is an included flash object (web-socket-js) that is used to
emulate websocket support on browsers without websocket support
(currently only Chrome has WebSocket support).

Javascript doesn't have a bytearray type, so what you get out of
a WebSocket object is just Javascript strings. Javascript has UTF-16
unicode strings and anything sent through the WebSocket gets converted
to UTF-8 and vice-versa. So, one additional (and necessary) function
of websockify is base64 encoding/decoding what is sent to/from the
browser.

Building web-socket-js emulator:

cd include/web-socket-js/flash-src
mxmlc -static-link-runtime-shared-libraries WebSocketMain.as

Rebuilding inflator.js

- Download pako from npm
Expand Down
3 changes: 2 additions & 1 deletion include/playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enable_test_mode = function () {
this._rfb_port = port;
this._rfb_password = (password !== undefined) ? password : "";
this._rfb_path = (path !== undefined) ? path : "";
this._sock.init('binary', 'ws');
this._updateState('ProtocolVersion', "Starting VNC handshake");
};
};
Expand All @@ -43,7 +44,7 @@ next_iteration = function () {
frame_length = VNC_frame_data.length;
test_state = 'running';
}

if (test_state !== 'running') { return; }

iteration += 1;
Expand Down
40 changes: 23 additions & 17 deletions include/rfb.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ var RFB;
'view_only': false, // Disable client mouse/keyboard
'xvp_password_sep': '@', // Separator for XVP password fields
'disconnectTimeout': 3, // Time (s) to wait for disconnection
'wsProtocols': ['binary', 'base64'], // Protocols to use in the WebSocket connection
'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection
'repeaterID': '', // [UltraVNC] RepeaterID to connect to
'viewportDrag': false, // Move the viewport on mouse drags

Expand Down Expand Up @@ -218,16 +218,8 @@ var RFB;
Util.Info("Using native WebSockets");
this._updateState('loaded', 'noVNC ready: native WebSockets, ' + rmode);
} else {
Util.Warn("Using web-socket-js bridge. Flash version: " + Util.Flash.version);
if (!Util.Flash || Util.Flash.version < 9) {
this._cleanupSocket('fatal');
throw new Exception("WebSockets or <a href='http://get.adobe.com/flashplayer'>Adobe Flash</a> is required");
} else if (document.location.href.substr(0, 7) === 'file://') {
this._cleanupSocket('fatal');
throw new Exception("'file://' URL is incompatible with Adobe Flash");
} else {
this._updateState('loaded', 'noVNC ready: WebSockets emulation, ' + rmode);
}
this._cleanupSocket('fatal');
throw new Error("WebSocket support is required to use noVNC");
}

Util.Debug("<< RFB.constructor");
Expand Down Expand Up @@ -363,8 +355,6 @@ var RFB;

_init_vars: function () {
// reset state
this._sock.init();

this._FBU.rects = 0;
this._FBU.subrects = 0; // RRE and HEXTILE
this._FBU.lines = 0; // RAW
Expand Down Expand Up @@ -760,7 +750,8 @@ var RFB;

if (this._sock.rQwait("auth challenge", 16)) { return false; }

var challenge = this._sock.rQshiftBytes(16);
// TODO(directxman12): make genDES not require an Array
var challenge = Array.prototype.slice.call(this._sock.rQshiftBytes(16));
var response = RFB.genDES(this._rfb_password, challenge);
this._sock.send(response);
this._updateState("SecurityResult");
Expand Down Expand Up @@ -1559,11 +1550,21 @@ var RFB;
rQi += this._FBU.bytes - 1;
} else {
if (this._FBU.subencoding & 0x02) { // Background
this._FBU.background = rQ.slice(rQi, rQi + this._fb_Bpp);
if (this._fb_Bpp == 1) {
this._FBU.background = rQ[rQi];
} else {
// fb_Bpp is 4
this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
}
rQi += this._fb_Bpp;
}
if (this._FBU.subencoding & 0x04) { // Foreground
this._FBU.foreground = rQ.slice(rQi, rQi + this._fb_Bpp);
if (this._fb_Bpp == 1) {
this._FBU.foreground = rQ[rQi];
} else {
// this._fb_Bpp is 4
this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
}
rQi += this._fb_Bpp;
}

Expand All @@ -1575,7 +1576,12 @@ var RFB;
for (var s = 0; s < subrects; s++) {
var color;
if (this._FBU.subencoding & 0x10) { // SubrectsColoured
color = rQ.slice(rQi, rQi + this._fb_Bpp);
if (this._fb_Bpp === 1) {
color = rQ[rQi];
} else {
// _fb_Bpp is 4
color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
}
rQi += this._fb_Bpp;
} else {
color = this._FBU.foreground;
Expand Down
1 change: 0 additions & 1 deletion include/web-socket-js-project
Submodule web-socket-js-project deleted from c0855c
109 changes: 0 additions & 109 deletions include/web-socket-js/README.txt

This file was deleted.

Binary file removed include/web-socket-js/WebSocketMain.swf
Binary file not shown.
Loading

0 comments on commit 38781d9

Please sign in to comment.