Commit 9ff86fb7 authored by Solly Ross's avatar Solly Ross

Use Typed Arrays for the send queue

This commit converts the send queue to use typed arrays, and converts
message creation functions in 'rfb.js' to create messages directly into
the socket's send queue.  This commit also removes the separate mouse array,
which is no longer needed.
parent d1800d09
This diff is collapsed.
...@@ -45,10 +45,14 @@ function Websock() { ...@@ -45,10 +45,14 @@ function Websock() {
this._rQlen = 0; // Next write position in the receive queue this._rQlen = 0; // Next write position in the receive queue
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB) this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
this._rQmax = this._rQbufferSize / 8; this._rQmax = this._rQbufferSize / 8;
this._sQ = []; // Send queue
// called in init: this._rQ = new Uint8Array(this._rQbufferSize); // called in init: this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ = null; // Receive queue this._rQ = null; // Receive queue
this._sQbufferSize = 1024 * 10; // 10 KiB
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
this._sQlen = 0;
this._sQ = null; // Send queue
this._mode = 'binary'; // Current WebSocket mode: 'binary', 'base64' this._mode = 'binary'; // Current WebSocket mode: 'binary', 'base64'
this.maxBufferedAmount = 200; this.maxBufferedAmount = 200;
...@@ -183,9 +187,9 @@ function Websock() { ...@@ -183,9 +187,9 @@ function Websock() {
} }
if (this._websocket.bufferedAmount < this.maxBufferedAmount) { if (this._websocket.bufferedAmount < this.maxBufferedAmount) {
if (this._sQ.length > 0) { if (this._sQlen > 0) {
this._websocket.send(this._encode_message()); this._websocket.send(this._encode_message());
this._sQ = []; this._sQlen = 0;
} }
return true; return true;
...@@ -197,8 +201,9 @@ function Websock() { ...@@ -197,8 +201,9 @@ function Websock() {
}, },
send: function (arr) { send: function (arr) {
this._sQ = this._sQ.concat(arr); this._sQ.set(arr, this._sQlen);
return this.flush(); this._sQlen += arr.length;
return this.flush();
}, },
send_string: function (str) { send_string: function (str) {
...@@ -218,12 +223,12 @@ function Websock() { ...@@ -218,12 +223,12 @@ function Websock() {
_allocate_buffers: function () { _allocate_buffers: function () {
this._rQ = new Uint8Array(this._rQbufferSize); this._rQ = new Uint8Array(this._rQbufferSize);
this._sQ = new Uint8Array(this._sQbufferSize);
}, },
init: function (protocols, ws_schema) { init: function (protocols, ws_schema) {
this._allocate_buffers(); this._allocate_buffers();
this._rQi = 0; this._rQi = 0;
this._sQ = [];
this._websocket = null; this._websocket = null;
// Check for full typed array support // Check for full typed array support
...@@ -327,7 +332,8 @@ function Websock() { ...@@ -327,7 +332,8 @@ function Websock() {
// private methods // private methods
_encode_message: function () { _encode_message: function () {
// Put in a binary arraybuffer // Put in a binary arraybuffer
return (new Uint8Array(this._sQ)).buffer; // according to the spec, you can send ArrayBufferViews with the send method
return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
}, },
_decode_message: function (data) { _decode_message: function (data) {
......
...@@ -24,6 +24,12 @@ chai.use(function (_chai, utils) { ...@@ -24,6 +24,12 @@ chai.use(function (_chai, utils) {
_chai.Assertion.addMethod('sent', function (target_data) { _chai.Assertion.addMethod('sent', function (target_data) {
var obj = this._obj; var obj = this._obj;
obj.inspect = function () {
var res = { _websocket: obj._websocket, rQi: obj._rQi, _rQ: new Uint8Array(obj._rQ.buffer, 0, obj._rQlen),
_sQ: new Uint8Array(obj._sQ.buffer, 0, obj._sQlen) };
res.prototype = obj;
return res;
};
var data = obj._websocket._get_sent_data(); var data = obj._websocket._get_sent_data();
var same = true; var same = true;
for (var i = 0; i < obj.length; i++) { for (var i = 0; i < obj.length; i++) {
...@@ -38,8 +44,8 @@ chai.use(function (_chai, utils) { ...@@ -38,8 +44,8 @@ chai.use(function (_chai, utils) {
this.assert(same, this.assert(same,
"expected #{this} to have sent the data #{exp}, but it actually sent #{act}", "expected #{this} to have sent the data #{exp}, but it actually sent #{act}",
"expected #{this} not to have sent the data #{act}", "expected #{this} not to have sent the data #{act}",
target_data, Array.prototype.slice.call(target_data),
data); Array.prototype.slice.call(data));
}); });
_chai.Assertion.addProperty('array', function () { _chai.Assertion.addProperty('array', function () {
......
...@@ -51,14 +51,9 @@ var FakeWebSocket; ...@@ -51,14 +51,9 @@ var FakeWebSocket;
}, },
_get_sent_data: function () { _get_sent_data: function () {
var arr = []; var res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount);
for (var i = 0; i < this.bufferedAmount; i++) {
arr[i] = this._send_queue[i];
}
this.bufferedAmount = 0; this.bufferedAmount = 0;
return res;
return arr;
}, },
_open: function (data) { _open: function (data) {
......
This diff is collapsed.
...@@ -173,7 +173,8 @@ describe('Websock', function() { ...@@ -173,7 +173,8 @@ describe('Websock', function() {
it('should actually send on the websocket if the websocket does not have too much buffered', function () { it('should actually send on the websocket if the websocket does not have too much buffered', function () {
sock.maxBufferedAmount = 10; sock.maxBufferedAmount = 10;
sock._websocket.bufferedAmount = 8; sock._websocket.bufferedAmount = 8;
sock._sQ = [1, 2, 3]; sock._sQ = new Uint8Array([1, 2, 3]);
sock._sQlen = 3;
var encoded = sock._encode_message(); var encoded = sock._encode_message();
sock.flush(); sock.flush();
...@@ -189,7 +190,7 @@ describe('Websock', function() { ...@@ -189,7 +190,7 @@ describe('Websock', function() {
}); });
it('should not call send if we do not have anything queued up', function () { it('should not call send if we do not have anything queued up', function () {
sock._sQ = []; sock._sQlen = 0;
sock.maxBufferedAmount = 10; sock.maxBufferedAmount = 10;
sock._websocket.bufferedAmount = 8; sock._websocket.bufferedAmount = 8;
...@@ -215,7 +216,7 @@ describe('Websock', function() { ...@@ -215,7 +216,7 @@ describe('Websock', function() {
it('should add to the send queue', function () { it('should add to the send queue', function () {
sock.send([1, 2, 3]); sock.send([1, 2, 3]);
var sq = sock.get_sQ(); var sq = sock.get_sQ();
expect(sock.get_sQ().slice(sq.length - 3)).to.deep.equal([1, 2, 3]); expect(new Uint8Array(sq.buffer, sock._sQlen - 3, 3)).to.array.equal(new Uint8Array([1, 2, 3]));
}); });
it('should call flush', function () { it('should call flush', function () {
...@@ -425,15 +426,16 @@ describe('Websock', function() { ...@@ -425,15 +426,16 @@ describe('Websock', function() {
sock._websocket._open(); sock._websocket._open();
}); });
it('should convert the send queue into an ArrayBuffer', function () { it('should only send the send queue up to the send queue length', function () {
sock._sQ = [1, 2, 3]; sock._sQ = new Uint8Array([1, 2, 3, 4, 5]);
var res = sock._encode_message(); // An ArrayBuffer sock._sQlen = 3;
expect(new Uint8Array(res)).to.deep.equal(new Uint8Array(res)); var res = sock._encode_message();
expect(res).to.array.equal(new Uint8Array([1, 2, 3]));
}); });
it('should properly pass the encoded data off to the actual WebSocket', function () { it('should properly pass the encoded data off to the actual WebSocket', function () {
sock.send([1, 2, 3]); sock.send([1, 2, 3]);
expect(sock._websocket._get_sent_data()).to.deep.equal([1, 2, 3]); expect(sock._websocket._get_sent_data()).to.array.equal(new Uint8Array([1, 2, 3]));
}); });
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment