websock.js: simpler binary support, protocols param.
Use a simpler method of enabling binary transfer over WebSockets. This still presents the user of websock.js with a plain javascript array for the receive queue data. However, if binary support is supported and requested then the transfer will be raw frames instead of base64 encoded. Lots of room for optimization here but for now correct is better than fast. Pull from websockify 17175afd7311c55abd8d
This commit is contained in:
parent
14717eb468
commit
fcff386b92
|
@ -299,7 +299,8 @@ function connect() {
|
||||||
uri += rfb_host + ":" + rfb_port + "/" + rfb_path;
|
uri += rfb_host + ":" + rfb_port + "/" + rfb_path;
|
||||||
}
|
}
|
||||||
Util.Info("connecting to " + uri);
|
Util.Info("connecting to " + uri);
|
||||||
ws.open(uri);
|
// TODO: make protocols a configurable
|
||||||
|
ws.open(uri, ['binary', 'base64']);
|
||||||
|
|
||||||
Util.Debug("<< RFB.connect");
|
Util.Debug("<< RFB.connect");
|
||||||
}
|
}
|
||||||
|
@ -1252,11 +1253,11 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
rQi += FBU.bytes - 1;
|
rQi += FBU.bytes - 1;
|
||||||
} else {
|
} else {
|
||||||
if (FBU.subencoding & 0x02) { // Background
|
if (FBU.subencoding & 0x02) { // Background
|
||||||
FBU.background = rQ.subarray(rQi, rQi + fb_Bpp);
|
FBU.background = rQ.slice(rQi, rQi + fb_Bpp);
|
||||||
rQi += fb_Bpp;
|
rQi += fb_Bpp;
|
||||||
}
|
}
|
||||||
if (FBU.subencoding & 0x04) { // Foreground
|
if (FBU.subencoding & 0x04) { // Foreground
|
||||||
FBU.foreground = rQ.subarray(rQi, rQi + fb_Bpp);
|
FBU.foreground = rQ.slice(rQi, rQi + fb_Bpp);
|
||||||
rQi += fb_Bpp;
|
rQi += fb_Bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1266,7 +1267,7 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
rQi += 1;
|
rQi += 1;
|
||||||
for (s = 0; s < subrects; s += 1) {
|
for (s = 0; s < subrects; s += 1) {
|
||||||
if (FBU.subencoding & 0x10) { // SubrectsColoured
|
if (FBU.subencoding & 0x10) { // SubrectsColoured
|
||||||
color = rQ.subarray(rQi, rQi + fb_Bpp);
|
color = rQ.slice(rQi, rQi + fb_Bpp);
|
||||||
rQi += fb_Bpp;
|
rQi += fb_Bpp;
|
||||||
} else {
|
} else {
|
||||||
color = FBU.foreground;
|
color = FBU.foreground;
|
||||||
|
|
|
@ -18,10 +18,6 @@ var Util = {};
|
||||||
* Make arrays quack
|
* Make arrays quack
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Array.prototype.subarray = function (start, end) {
|
|
||||||
this.slice(start, end);
|
|
||||||
};
|
|
||||||
|
|
||||||
Array.prototype.push8 = function (num) {
|
Array.prototype.push8 = function (num) {
|
||||||
this.push(num & 0xFF);
|
this.push(num & 0xFF);
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,7 +61,6 @@ function Websock() {
|
||||||
|
|
||||||
var api = {}, // Public API
|
var api = {}, // Public API
|
||||||
websocket = null, // WebSocket object
|
websocket = null, // WebSocket object
|
||||||
protocols, // Protocols to request in priority order
|
|
||||||
mode = 'base64',
|
mode = 'base64',
|
||||||
rQ = [], // Receive queue
|
rQ = [], // Receive queue
|
||||||
rQi = 0, // Receive queue index
|
rQi = 0, // Receive queue index
|
||||||
|
@ -125,46 +124,24 @@ function rQshift32() {
|
||||||
(rQ[rQi++] << 8) +
|
(rQ[rQi++] << 8) +
|
||||||
(rQ[rQi++] );
|
(rQ[rQi++] );
|
||||||
}
|
}
|
||||||
function rQslice(start, end) {
|
|
||||||
if (mode === 'binary') {
|
|
||||||
if (end) {
|
|
||||||
return rQ.subarray(rQi + start, rQi + end);
|
|
||||||
} else {
|
|
||||||
return rQ.subarray(rQi + start);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (end) {
|
|
||||||
return rQ.slice(rQi + start, rQi + end);
|
|
||||||
} else {
|
|
||||||
return rQ.slice(rQi + start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rQshiftStr(len) {
|
function rQshiftStr(len) {
|
||||||
if (typeof(len) === 'undefined') { len = rQlen(); }
|
if (typeof(len) === 'undefined') { len = rQlen(); }
|
||||||
var arr = rQslice(0, len);
|
var arr = rQ.slice(rQi, rQi + len);
|
||||||
rQi += len;
|
rQi += len;
|
||||||
return String.fromCharCode.apply(null, arr);
|
return String.fromCharCode.apply(null, arr);
|
||||||
}
|
}
|
||||||
function rQshiftBytes(len) {
|
function rQshiftBytes(len) {
|
||||||
if (typeof(len) === 'undefined') { len = rQlen(); }
|
if (typeof(len) === 'undefined') { len = rQlen(); }
|
||||||
var a = rQslice(0, len), b = [];
|
|
||||||
if (mode === 'binary') {
|
|
||||||
// Convert to plain array
|
|
||||||
b.push.apply(b, a);
|
|
||||||
} else {
|
|
||||||
// Already plain array, just return the original
|
|
||||||
b = a
|
|
||||||
}
|
|
||||||
rQi += len;
|
rQi += len;
|
||||||
return b;
|
return rQ.slice(rQi-len, rQi);
|
||||||
}
|
}
|
||||||
function rQshiftArray(len) {
|
|
||||||
if (typeof(len) === 'undefined') { len = rQlen(); }
|
function rQslice(start, end) {
|
||||||
var a = rQslice(0, len);
|
if (end) {
|
||||||
rQi += len;
|
return rQ.slice(rQi + start, rQi + end);
|
||||||
return a;
|
} else {
|
||||||
|
return rQ.slice(rQi + start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
|
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
|
||||||
|
@ -202,14 +179,10 @@ function encode_message() {
|
||||||
function decode_message(data) {
|
function decode_message(data) {
|
||||||
//Util.Debug(">> decode_message: " + data);
|
//Util.Debug(">> decode_message: " + data);
|
||||||
if (mode === 'binary') {
|
if (mode === 'binary') {
|
||||||
// Create new arraybuffer and dump old and new data into it
|
// push arraybuffer values onto the end
|
||||||
// TODO: this could be far more efficient and re-use the array
|
rQ.push.apply(rQ, (new Uint8Array(data)));
|
||||||
var new_rQ = new Uint8Array(rQ.length + data.byteLength);
|
|
||||||
new_rQ.set(rQ);
|
|
||||||
new_rQ.set(new Uint8Array(data), rQ.length);
|
|
||||||
rQ = new_rQ;
|
|
||||||
} else {
|
} else {
|
||||||
/* base64 decode and concat to the end */
|
// base64 decode and concat to the end
|
||||||
rQ = rQ.concat(Base64.decode(data, 0));
|
rQ = rQ.concat(Base64.decode(data, 0));
|
||||||
}
|
}
|
||||||
//Util.Debug(">> decode_message, rQ: " + rQ);
|
//Util.Debug(">> decode_message, rQ: " + rQ);
|
||||||
|
@ -265,7 +238,7 @@ function recv_message(e) {
|
||||||
// Compact the receive queue
|
// Compact the receive queue
|
||||||
if (rQ.length > rQmax) {
|
if (rQ.length > rQmax) {
|
||||||
//Util.Debug("Compacting receive queue");
|
//Util.Debug("Compacting receive queue");
|
||||||
rQ = rQslice(rQi);
|
rQ = rQ.slice(rQi);
|
||||||
rQi = 0;
|
rQi = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,40 +267,62 @@ function on(evt, handler) {
|
||||||
eventHandlers[evt] = handler;
|
eventHandlers[evt] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init(protocols) {
|
||||||
rQ = [];
|
rQ = [];
|
||||||
rQi = 0;
|
rQi = 0;
|
||||||
sQ = [];
|
sQ = [];
|
||||||
websocket = null,
|
websocket = null;
|
||||||
protocols = "base64";
|
|
||||||
|
|
||||||
var bt = false,
|
var bt = false,
|
||||||
wsbt = false;
|
wsbt = false,
|
||||||
|
try_binary = false;
|
||||||
|
|
||||||
|
// Check for full typed array support
|
||||||
if (('Uint8Array' in window) &&
|
if (('Uint8Array' in window) &&
|
||||||
('set' in Uint8Array.prototype)) {
|
('set' in Uint8Array.prototype)) {
|
||||||
bt = true;
|
bt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for full binary type support in WebSockets
|
||||||
// TODO: this sucks, the property should exist on the prototype
|
// TODO: this sucks, the property should exist on the prototype
|
||||||
// but it does not.
|
// but it does not.
|
||||||
try {
|
try {
|
||||||
if (bt && ('binaryType' in (new WebSocket("ws://localhost:17523")))) {
|
if (bt && ('binaryType' in (new WebSocket("ws://localhost:17523")))) {
|
||||||
|
Util.Info("Detected binaryType support in WebSockets");
|
||||||
wsbt = true;
|
wsbt = true;
|
||||||
}
|
}
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
// Just ignore failed test localhost connections
|
// Just ignore failed test localhost connections
|
||||||
}
|
}
|
||||||
if (bt && wsbt) {
|
|
||||||
Util.Info("Detected binaryType support in WebSockets");
|
// Default protocols if not specified
|
||||||
protocols = ['binary', 'base64'];
|
if (typeof(protocols) === "undefined") {
|
||||||
} else {
|
if (wsbt) {
|
||||||
Util.Info("No binaryType support in WebSockets, using base64 encoding");
|
protocols = ['binary', 'base64'];
|
||||||
protocols = 'base64';
|
} else {
|
||||||
|
protocols = 'base64';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no binary support, make sure it was not requested
|
||||||
|
if (!wsbt) {
|
||||||
|
if (protocols === 'binary') {
|
||||||
|
throw("WebSocket binary sub-protocol requested but not supported");
|
||||||
|
}
|
||||||
|
if (typeof(protocols) === "object") {
|
||||||
|
for (var i = 0; i < protocols.length; i++) {
|
||||||
|
if (protocols[i] === 'binary') {
|
||||||
|
throw("WebSocket binary sub-protocol requested but not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
function open(uri) {
|
function open(uri, protocols) {
|
||||||
init();
|
protocols = init(protocols);
|
||||||
|
|
||||||
if (test_mode) {
|
if (test_mode) {
|
||||||
websocket = {};
|
websocket = {};
|
||||||
|
|
Loading…
Reference in New Issue