Add getters/setter to websock

This commit is contained in:
Juanjo Diaz 2018-12-08 17:31:20 +02:00
parent 18439b0680
commit 8a189a6291
7 changed files with 72 additions and 84 deletions

View File

@ -32,8 +32,8 @@ export default class HextileDecoder {
return false; return false;
} }
let rQ = sock.get_rQ(); let rQ = sock.rQ;
let rQi = sock.get_rQi(); let rQi = sock.rQi;
let subencoding = rQ[rQi]; // Peek let subencoding = rQ[rQi]; // Peek
if (subencoding > 30) { // Raw if (subencoding > 30) { // Raw
@ -129,7 +129,6 @@ export default class HextileDecoder {
} }
display.finishTile(); display.finishTile();
} }
sock.set_rQi(rQi);
this._lastsubencoding = subencoding; this._lastsubencoding = subencoding;
this._tiles--; this._tiles--;
} }

View File

@ -28,9 +28,9 @@ export default class RawDecoder {
const cur_y = y + (height - this._lines); const cur_y = y + (height - this._lines);
const curr_height = Math.min(this._lines, const curr_height = Math.min(this._lines,
Math.floor(sock.rQlen() / bytesPerLine)); Math.floor(sock.rQlen / bytesPerLine));
let data = sock.get_rQ(); let data = sock.rQ;
let index = sock.get_rQi(); let index = sock.rQi;
// Convert data if needed // Convert data if needed
if (depth == 8) { if (depth == 8) {

View File

@ -78,8 +78,8 @@ export default class TightDecoder {
return false; return false;
} }
const rQi = sock.get_rQi(); const rQi = sock.rQi;
const rQ = sock.rQwhole(); const rQ = sock.rQ;
display.fillRect(x, y, width, height, display.fillRect(x, y, width, height,
[rQ[rQi + 2], rQ[rQi + 1], rQ[rQi]], false); [rQ[rQi + 2], rQ[rQi + 1], rQ[rQi]], false);

View File

@ -681,7 +681,7 @@ export default class RFB extends EventTargetMixin {
} }
_handle_message() { _handle_message() {
if (this._sock.rQlen() === 0) { if (this._sock.rQlen === 0) {
Log.Warn("handle_message called on an empty receive queue"); Log.Warn("handle_message called on an empty receive queue");
return; return;
} }
@ -698,7 +698,7 @@ export default class RFB extends EventTargetMixin {
if (!this._normal_msg()) { if (!this._normal_msg()) {
break; break;
} }
if (this._sock.rQlen() === 0) { if (this._sock.rQlen === 0) {
break; break;
} }
} }
@ -779,7 +779,7 @@ export default class RFB extends EventTargetMixin {
// Message Handlers // Message Handlers
_negotiate_protocol_version() { _negotiate_protocol_version() {
if (this._sock.rQlen() < 12) { if (this._sock.rQlen < 12) {
return this._fail("Received incomplete protocol version."); return this._fail("Received incomplete protocol version.");
} }
@ -1360,7 +1360,7 @@ export default class RFB extends EventTargetMixin {
_handle_xvp_msg() { _handle_xvp_msg() {
if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; } if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; }
this._sock.rQskip8(); // Padding this._sock.rQskipBytes(1); // Padding
const xvp_ver = this._sock.rQshift8(); const xvp_ver = this._sock.rQshift8();
const xvp_msg = this._sock.rQshift8(); const xvp_msg = this._sock.rQshift8();
@ -1442,7 +1442,7 @@ export default class RFB extends EventTargetMixin {
_onFlush() { _onFlush() {
this._flushing = false; this._flushing = false;
// Resume processing // Resume processing
if (this._sock.rQlen() > 0) { if (this._sock.rQlen > 0) {
this._handle_message(); this._handle_message();
} }
} }
@ -1450,7 +1450,7 @@ export default class RFB extends EventTargetMixin {
_framebufferUpdate() { _framebufferUpdate() {
if (this._FBU.rects === 0) { if (this._FBU.rects === 0) {
if (this._sock.rQwait("FBU header", 3, 1)) { return false; } if (this._sock.rQwait("FBU header", 3, 1)) { return false; }
this._sock.rQskip8(); // Padding this._sock.rQskipBytes(1); // Padding
this._FBU.rects = this._sock.rQshift16(); this._FBU.rects = this._sock.rQshift16();
// Make sure the previous frame is fully rendered first // Make sure the previous frame is fully rendered first

View File

@ -45,24 +45,24 @@ export default class Websock {
} }
// Getters and Setters // Getters and Setters
get_sQ() { get sQ() {
return this._sQ; return this._sQ;
} }
get_rQ() { get rQ() {
return this._rQ; return this._rQ;
} }
get_rQi() { get rQi() {
return this._rQi; return this._rQi;
} }
set_rQi(val) { set rQi(val) {
this._rQi = val; this._rQi = val;
} }
// Receive Queue // Receive Queue
rQlen() { get rQlen() {
return this._rQlen - this._rQi; return this._rQlen - this._rQi;
} }
@ -70,17 +70,15 @@ export default class Websock {
return this._rQ[this._rQi]; return this._rQ[this._rQi];
} }
rQskipBytes(bytes) {
this._rQi += bytes;
}
rQshift8() { rQshift8() {
return this._rQ[this._rQi++]; return this._rQ[this._rQi++];
} }
rQskip8() {
this._rQi++;
}
rQskipBytes(num) {
this._rQi += num;
}
// TODO(directxman12): test performance with these vs a DataView // TODO(directxman12): test performance with these vs a DataView
rQshift16() { rQshift16() {
@ -96,7 +94,7 @@ export default class Websock {
} }
rQshiftStr(len) { rQshiftStr(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); } if (typeof(len) === 'undefined') { len = this.rQlen; }
let str = ""; let str = "";
// Handle large arrays in steps to avoid long strings on the stack // Handle large arrays in steps to avoid long strings on the stack
for (let i = 0; i < len; i += 4096) { for (let i = 0; i < len; i += 4096) {
@ -107,36 +105,27 @@ export default class Websock {
} }
rQshiftBytes(len) { rQshiftBytes(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); } if (typeof(len) === 'undefined') { len = this.rQlen; }
this._rQi += len; this._rQi += len;
return new Uint8Array(this._rQ.buffer, this._rQi - len, len); return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
} }
rQshiftTo(target, len) { rQshiftTo(target, len) {
if (len === undefined) { len = this.rQlen(); } if (len === undefined) { len = this.rQlen; }
// TODO: make this just use set with views when using a ArrayBuffer to store the rQ // TODO: make this just use set with views when using a ArrayBuffer to store the rQ
target.set(new Uint8Array(this._rQ.buffer, this._rQi, len)); target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
this._rQi += len; this._rQi += len;
} }
rQwhole() { rQslice(start, end = this.rQlen) {
return new Uint8Array(this._rQ.buffer, 0, this._rQlen); return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
}
rQslice(start, end) {
if (end) {
return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
} else {
return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._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)
// to be available in the receive queue. Return true if we need to // to be available in the receive queue. Return true if we need to
// wait (and possibly print a debug message), otherwise false. // wait (and possibly print a debug message), otherwise false.
rQwait(msg, num, goback) { rQwait(msg, num, goback) {
const rQlen = this._rQlen - this._rQi; // Skip rQlen() function call if (this.rQlen < num) {
if (rQlen < num) {
if (goback) { if (goback) {
if (this._rQi < goback) { if (this._rQi < goback) {
throw new Error("rQwait cannot backup " + goback + " bytes"); throw new Error("rQwait cannot backup " + goback + " bytes");
@ -235,21 +224,21 @@ export default class Websock {
} }
_expand_compact_rQ(min_fit) { _expand_compact_rQ(min_fit) {
const resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2; const resizeNeeded = min_fit || this.rQlen > this._rQbufferSize / 2;
if (resizeNeeded) { if (resizeNeeded) {
if (!min_fit) { if (!min_fit) {
// just double the size if we need to do compaction // just double the size if we need to do compaction
this._rQbufferSize *= 2; this._rQbufferSize *= 2;
} else { } else {
// otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8 // otherwise, make sure we satisy rQlen - rQi + min_fit < rQbufferSize / 8
this._rQbufferSize = (this._rQlen - this._rQi + min_fit) * 8; this._rQbufferSize = (this.rQlen + min_fit) * 8;
} }
} }
// we don't want to grow unboundedly // we don't want to grow unboundedly
if (this._rQbufferSize > MAX_RQ_GROW_SIZE) { if (this._rQbufferSize > MAX_RQ_GROW_SIZE) {
this._rQbufferSize = MAX_RQ_GROW_SIZE; this._rQbufferSize = MAX_RQ_GROW_SIZE;
if (this._rQbufferSize - this._rQlen - this._rQi < min_fit) { if (this._rQbufferSize - this.rQlen < min_fit) {
throw new Error("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit"); throw new Error("Receive Queue buffer exceeded " + MAX_RQ_GROW_SIZE + " bytes, and the new message could not fit");
} }
} }
@ -283,7 +272,7 @@ export default class Websock {
_recv_message(e) { _recv_message(e) {
this._decode_message(e.data); this._decode_message(e.data);
if (this.rQlen() > 0) { if (this.rQlen > 0) {
this._eventHandlers.message(); this._eventHandlers.message();
// Compact the receive queue // Compact the receive queue
if (this._rQlen == this._rQi) { if (this._rQlen == this._rQi) {

View File

@ -1635,7 +1635,7 @@ describe('Remote Frame Buffer Protocol Client', function () {
client._sock._websocket._receive_data(new Uint8Array([0, 0, 0, 3])); client._sock._websocket._receive_data(new Uint8Array([0, 0, 0, 3]));
expect(client._sock._websocket._get_sent_data()).to.have.length(0); expect(client._sock._websocket._get_sent_data()).to.have.length(0);
client._framebufferUpdate = function () { this._sock.rQskip8(); return true; }; // we magically have enough data client._framebufferUpdate = function () { this._sock.rQskipBytes(1); return true; }; // we magically have enough data
// 247 should *not* be used as the message type here // 247 should *not* be used as the message type here
client._sock._websocket._receive_data(new Uint8Array([247])); client._sock._websocket._receive_data(new Uint8Array([247]));
expect(client._sock).to.have.sent(expected_msg._sQ); expect(client._sock).to.have.sent(expected_msg._sQ);

View File

@ -19,70 +19,70 @@ describe('Websock', function () {
}); });
describe('rQlen', function () { describe('rQlen', function () {
it('should return the length of the receive queue', function () { it('should return the length of the receive queue', function () {
sock.set_rQi(0); sock.rQi = 0;
expect(sock.rQlen()).to.equal(RQ_TEMPLATE.length); expect(sock.rQlen).to.equal(RQ_TEMPLATE.length);
}); });
it("should return the proper length if we read some from the receive queue", function () { it("should return the proper length if we read some from the receive queue", function () {
sock.set_rQi(1); sock.rQi = 1;
expect(sock.rQlen()).to.equal(RQ_TEMPLATE.length - 1); expect(sock.rQlen).to.equal(RQ_TEMPLATE.length - 1);
}); });
}); });
describe('rQpeek8', function () { describe('rQpeek8', function () {
it('should peek at the next byte without poping it off the queue', function () { it('should peek at the next byte without poping it off the queue', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
const peek = sock.rQpeek8(); const peek = sock.rQpeek8();
expect(sock.rQpeek8()).to.equal(peek); expect(sock.rQpeek8()).to.equal(peek);
expect(sock.rQlen()).to.equal(bef_len); expect(sock.rQlen).to.equal(bef_len);
}); });
}); });
describe('rQshift8', function () { describe('rQshift8()', function () {
it('should pop a single byte from the receive queue', function () { it('should pop a single byte from the receive queue', function () {
const peek = sock.rQpeek8(); const peek = sock.rQpeek8();
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
expect(sock.rQshift8()).to.equal(peek); expect(sock.rQshift8()).to.equal(peek);
expect(sock.rQlen()).to.equal(bef_len - 1); expect(sock.rQlen).to.equal(bef_len - 1);
}); });
}); });
describe('rQshift16', function () { describe('rQshift16()', function () {
it('should pop two bytes from the receive queue and return a single number', function () { it('should pop two bytes from the receive queue and return a single number', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
const expected = (RQ_TEMPLATE[0] << 8) + RQ_TEMPLATE[1]; const expected = (RQ_TEMPLATE[0] << 8) + RQ_TEMPLATE[1];
expect(sock.rQshift16()).to.equal(expected); expect(sock.rQshift16()).to.equal(expected);
expect(sock.rQlen()).to.equal(bef_len - 2); expect(sock.rQlen).to.equal(bef_len - 2);
}); });
}); });
describe('rQshift32', function () { describe('rQshift32()', function () {
it('should pop four bytes from the receive queue and return a single number', function () { it('should pop four bytes from the receive queue and return a single number', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
const expected = (RQ_TEMPLATE[0] << 24) + const expected = (RQ_TEMPLATE[0] << 24) +
(RQ_TEMPLATE[1] << 16) + (RQ_TEMPLATE[1] << 16) +
(RQ_TEMPLATE[2] << 8) + (RQ_TEMPLATE[2] << 8) +
RQ_TEMPLATE[3]; RQ_TEMPLATE[3];
expect(sock.rQshift32()).to.equal(expected); expect(sock.rQshift32()).to.equal(expected);
expect(sock.rQlen()).to.equal(bef_len - 4); expect(sock.rQlen).to.equal(bef_len - 4);
}); });
}); });
describe('rQshiftStr', function () { describe('rQshiftStr', function () {
it('should shift the given number of bytes off of the receive queue and return a string', function () { it('should shift the given number of bytes off of the receive queue and return a string', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
const bef_rQi = sock.get_rQi(); const bef_rQi = sock.rQi;
const shifted = sock.rQshiftStr(3); const shifted = sock.rQshiftStr(3);
expect(shifted).to.be.a('string'); expect(shifted).to.be.a('string');
expect(shifted).to.equal(String.fromCharCode.apply(null, Array.prototype.slice.call(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3)))); expect(shifted).to.equal(String.fromCharCode.apply(null, Array.prototype.slice.call(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3))));
expect(sock.rQlen()).to.equal(bef_len - 3); expect(sock.rQlen).to.equal(bef_len - 3);
}); });
it('should shift the entire rest of the queue off if no length is given', function () { it('should shift the entire rest of the queue off if no length is given', function () {
sock.rQshiftStr(); sock.rQshiftStr();
expect(sock.rQlen()).to.equal(0); expect(sock.rQlen).to.equal(0);
}); });
it('should be able to handle very large strings', function () { it('should be able to handle very large strings', function () {
@ -106,35 +106,35 @@ describe('Websock', function () {
const shifted = sock.rQshiftStr(); const shifted = sock.rQshiftStr();
expect(shifted).to.be.equal(expected); expect(shifted).to.be.equal(expected);
expect(sock.rQlen()).to.equal(0); expect(sock.rQlen).to.equal(0);
}); });
}); });
describe('rQshiftBytes', function () { describe('rQshiftBytes', function () {
it('should shift the given number of bytes of the receive queue and return an array', function () { it('should shift the given number of bytes of the receive queue and return an array', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
const bef_rQi = sock.get_rQi(); const bef_rQi = sock.rQi;
const shifted = sock.rQshiftBytes(3); const shifted = sock.rQshiftBytes(3);
expect(shifted).to.be.an.instanceof(Uint8Array); expect(shifted).to.be.an.instanceof(Uint8Array);
expect(shifted).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3)); expect(shifted).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, bef_rQi, 3));
expect(sock.rQlen()).to.equal(bef_len - 3); expect(sock.rQlen).to.equal(bef_len - 3);
}); });
it('should shift the entire rest of the queue off if no length is given', function () { it('should shift the entire rest of the queue off if no length is given', function () {
sock.rQshiftBytes(); sock.rQshiftBytes();
expect(sock.rQlen()).to.equal(0); expect(sock.rQlen).to.equal(0);
}); });
}); });
describe('rQslice', function () { describe('rQslice', function () {
beforeEach(function () { beforeEach(function () {
sock.set_rQi(0); sock.rQi = 0;
}); });
it('should not modify the receive queue', function () { it('should not modify the receive queue', function () {
const bef_len = sock.rQlen(); const bef_len = sock.rQlen;
sock.rQslice(0, 2); sock.rQslice(0, 2);
expect(sock.rQlen()).to.equal(bef_len); expect(sock.rQlen).to.equal(bef_len);
}); });
it('should return an array containing the given slice of the receive queue', function () { it('should return an array containing the given slice of the receive queue', function () {
@ -150,14 +150,14 @@ describe('Websock', function () {
}); });
it('should take the current rQi in to account', function () { it('should take the current rQi in to account', function () {
sock.set_rQi(1); sock.rQi = 1;
expect(sock.rQslice(0, 2)).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 1, 2)); expect(sock.rQslice(0, 2)).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 1, 2));
}); });
}); });
describe('rQwait', function () { describe('rQwait', function () {
beforeEach(function () { beforeEach(function () {
sock.set_rQi(0); sock.rQi = 0;
}); });
it('should return true if there are not enough bytes in the receive queue', function () { it('should return true if there are not enough bytes in the receive queue', function () {
@ -169,20 +169,20 @@ describe('Websock', function () {
}); });
it('should return true and reduce rQi by "goback" if there are not enough bytes', function () { it('should return true and reduce rQi by "goback" if there are not enough bytes', function () {
sock.set_rQi(5); sock.rQi = 5;
expect(sock.rQwait('hi', RQ_TEMPLATE.length, 4)).to.be.true; expect(sock.rQwait('hi', RQ_TEMPLATE.length, 4)).to.be.true;
expect(sock.get_rQi()).to.equal(1); expect(sock.rQi).to.equal(1);
}); });
it('should raise an error if we try to go back more than possible', function () { it('should raise an error if we try to go back more than possible', function () {
sock.set_rQi(5); sock.rQi = 5;
expect(() => sock.rQwait('hi', RQ_TEMPLATE.length, 6)).to.throw(Error); expect(() => sock.rQwait('hi', RQ_TEMPLATE.length, 6)).to.throw(Error);
}); });
it('should not reduce rQi if there are enough bytes', function () { it('should not reduce rQi if there are enough bytes', function () {
sock.set_rQi(5); sock.rQi = 5;
sock.rQwait('hi', 1, 6); sock.rQwait('hi', 1, 6);
expect(sock.get_rQi()).to.equal(5); expect(sock.rQi).to.equal(5);
}); });
}); });
@ -222,7 +222,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]);
const sq = sock.get_sQ(); const sq = sock.sQ;
expect(new Uint8Array(sq.buffer, sock._sQlen - 3, 3)).to.array.equal(new Uint8Array([1, 2, 3])); expect(new Uint8Array(sq.buffer, sock._sQlen - 3, 3)).to.array.equal(new Uint8Array([1, 2, 3]));
}); });
@ -389,26 +389,26 @@ describe('Websock', function () {
// test, otherwise the receive queue could become very large very quickly // test, otherwise the receive queue could become very large very quickly
sock._rQ = new Uint8Array([0, 1, 2, 3, 4, 5, 0, 0, 0, 0]); sock._rQ = new Uint8Array([0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
sock._rQlen = 6; sock._rQlen = 6;
sock.set_rQi(6); sock.rQi = 6;
sock._rQmax = 3; sock._rQmax = 3;
const msg = { data: new Uint8Array([1, 2, 3]).buffer }; const msg = { data: new Uint8Array([1, 2, 3]).buffer };
sock._mode = 'binary'; sock._mode = 'binary';
sock._recv_message(msg); sock._recv_message(msg);
expect(sock._rQlen).to.equal(3); expect(sock._rQlen).to.equal(3);
expect(sock.get_rQi()).to.equal(0); expect(sock.rQi).to.equal(0);
}); });
it('should automatically resize the receive queue if the incoming message is too large', function () { it('should automatically resize the receive queue if the incoming message is too large', function () {
sock._rQ = new Uint8Array(20); sock._rQ = new Uint8Array(20);
sock._rQlen = 0; sock._rQlen = 0;
sock.set_rQi(0); sock.rQi = 0;
sock._rQbufferSize = 20; sock._rQbufferSize = 20;
sock._rQmax = 2; sock._rQmax = 2;
const msg = { data: new Uint8Array(30).buffer }; const msg = { data: new Uint8Array(30).buffer };
sock._mode = 'binary'; sock._mode = 'binary';
sock._recv_message(msg); sock._recv_message(msg);
expect(sock._rQlen).to.equal(30); expect(sock._rQlen).to.equal(30);
expect(sock.get_rQi()).to.equal(0); expect(sock.rQi).to.equal(0);
expect(sock._rQ.length).to.equal(240); // keep the invariant that rQbufferSize / 8 >= rQlen expect(sock._rQ.length).to.equal(240); // keep the invariant that rQbufferSize / 8 >= rQlen
}); });
}); });