Stop direct access to socket buffer
Use proper accessor functions instead of poking around in internal buffers.
This commit is contained in:
parent
fb3c8f64e9
commit
0180bc81c1
|
@ -31,10 +31,7 @@ export default class HextileDecoder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rQ = sock.rQ;
|
let subencoding = sock.rQpeek8();
|
||||||
let rQi = sock.rQi;
|
|
||||||
|
|
||||||
let subencoding = rQ[rQi]; // Peek
|
|
||||||
if (subencoding > 30) { // Raw
|
if (subencoding > 30) { // Raw
|
||||||
throw new Error("Illegal hextile subencoding (subencoding: " +
|
throw new Error("Illegal hextile subencoding (subencoding: " +
|
||||||
subencoding + ")");
|
subencoding + ")");
|
||||||
|
@ -65,7 +62,7 @@ export default class HextileDecoder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let subrects = rQ[rQi + bytes - 1]; // Peek
|
let subrects = sock.rQpeekBytes(bytes).at(-1);
|
||||||
if (subencoding & 0x10) { // SubrectsColoured
|
if (subencoding & 0x10) { // SubrectsColoured
|
||||||
bytes += subrects * (4 + 2);
|
bytes += subrects * (4 + 2);
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,7 +76,7 @@ export default class HextileDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We know the encoding and have a whole tile
|
// We know the encoding and have a whole tile
|
||||||
rQi++;
|
sock.rQshift8();
|
||||||
if (subencoding === 0) {
|
if (subencoding === 0) {
|
||||||
if (this._lastsubencoding & 0x01) {
|
if (this._lastsubencoding & 0x01) {
|
||||||
// Weird: ignore blanks are RAW
|
// Weird: ignore blanks are RAW
|
||||||
|
@ -89,42 +86,36 @@ export default class HextileDecoder {
|
||||||
}
|
}
|
||||||
} else if (subencoding & 0x01) { // Raw
|
} else if (subencoding & 0x01) { // Raw
|
||||||
let pixels = tw * th;
|
let pixels = tw * th;
|
||||||
|
let data = sock.rQshiftBytes(pixels * 4);
|
||||||
// Max sure the image is fully opaque
|
// Max sure the image is fully opaque
|
||||||
for (let i = 0;i < pixels;i++) {
|
for (let i = 0;i < pixels;i++) {
|
||||||
rQ[rQi + i * 4 + 3] = 255;
|
data[i * 4 + 3] = 255;
|
||||||
}
|
}
|
||||||
display.blitImage(tx, ty, tw, th, rQ, rQi);
|
display.blitImage(tx, ty, tw, th, data, 0);
|
||||||
rQi += bytes - 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (subencoding & 0x02) { // Background
|
if (subencoding & 0x02) { // Background
|
||||||
this._background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
|
this._background = new Uint8Array(sock.rQshiftBytes(4));
|
||||||
rQi += 4;
|
|
||||||
}
|
}
|
||||||
if (subencoding & 0x04) { // Foreground
|
if (subencoding & 0x04) { // Foreground
|
||||||
this._foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
|
this._foreground = new Uint8Array(sock.rQshiftBytes(4));
|
||||||
rQi += 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._startTile(tx, ty, tw, th, this._background);
|
this._startTile(tx, ty, tw, th, this._background);
|
||||||
if (subencoding & 0x08) { // AnySubrects
|
if (subencoding & 0x08) { // AnySubrects
|
||||||
let subrects = rQ[rQi];
|
let subrects = sock.rQshift8();
|
||||||
rQi++;
|
|
||||||
|
|
||||||
for (let s = 0; s < subrects; s++) {
|
for (let s = 0; s < subrects; s++) {
|
||||||
let color;
|
let color;
|
||||||
if (subencoding & 0x10) { // SubrectsColoured
|
if (subencoding & 0x10) { // SubrectsColoured
|
||||||
color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
|
color = sock.rQshiftBytes(4);
|
||||||
rQi += 4;
|
|
||||||
} else {
|
} else {
|
||||||
color = this._foreground;
|
color = this._foreground;
|
||||||
}
|
}
|
||||||
const xy = rQ[rQi];
|
const xy = sock.rQshift8();
|
||||||
rQi++;
|
|
||||||
const sx = (xy >> 4);
|
const sx = (xy >> 4);
|
||||||
const sy = (xy & 0x0f);
|
const sy = (xy & 0x0f);
|
||||||
|
|
||||||
const wh = rQ[rQi];
|
const wh = sock.rQshift8();
|
||||||
rQi++;
|
|
||||||
const sw = (wh >> 4) + 1;
|
const sw = (wh >> 4) + 1;
|
||||||
const sh = (wh & 0x0f) + 1;
|
const sh = (wh & 0x0f) + 1;
|
||||||
|
|
||||||
|
@ -133,7 +124,6 @@ export default class HextileDecoder {
|
||||||
}
|
}
|
||||||
this._finishTile(display);
|
this._finishTile(display);
|
||||||
}
|
}
|
||||||
sock.rQi = rQi;
|
|
||||||
this._lastsubencoding = subencoding;
|
this._lastsubencoding = subencoding;
|
||||||
this._tiles--;
|
this._tiles--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,29 +33,26 @@ export default class RawDecoder {
|
||||||
Math.floor(sock.rQlen / bytesPerLine));
|
Math.floor(sock.rQlen / bytesPerLine));
|
||||||
const pixels = width * currHeight;
|
const pixels = width * currHeight;
|
||||||
|
|
||||||
let data = sock.rQ;
|
let data = sock.rQshiftBytes(currHeight * bytesPerLine);
|
||||||
let index = sock.rQi;
|
|
||||||
|
|
||||||
// Convert data if needed
|
// Convert data if needed
|
||||||
if (depth == 8) {
|
if (depth == 8) {
|
||||||
const newdata = new Uint8Array(pixels * 4);
|
const newdata = new Uint8Array(pixels * 4);
|
||||||
for (let i = 0; i < pixels; i++) {
|
for (let i = 0; i < pixels; i++) {
|
||||||
newdata[i * 4 + 0] = ((data[index + i] >> 0) & 0x3) * 255 / 3;
|
newdata[i * 4 + 0] = ((data[i] >> 0) & 0x3) * 255 / 3;
|
||||||
newdata[i * 4 + 1] = ((data[index + i] >> 2) & 0x3) * 255 / 3;
|
newdata[i * 4 + 1] = ((data[i] >> 2) & 0x3) * 255 / 3;
|
||||||
newdata[i * 4 + 2] = ((data[index + i] >> 4) & 0x3) * 255 / 3;
|
newdata[i * 4 + 2] = ((data[i] >> 4) & 0x3) * 255 / 3;
|
||||||
newdata[i * 4 + 3] = 255;
|
newdata[i * 4 + 3] = 255;
|
||||||
}
|
}
|
||||||
data = newdata;
|
data = newdata;
|
||||||
index = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max sure the image is fully opaque
|
// Max sure the image is fully opaque
|
||||||
for (let i = 0; i < pixels; i++) {
|
for (let i = 0; i < pixels; i++) {
|
||||||
data[index + i * 4 + 3] = 255;
|
data[i * 4 + 3] = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
display.blitImage(x, curY, width, currHeight, data, index);
|
display.blitImage(x, curY, width, currHeight, data, 0);
|
||||||
sock.rQskipBytes(currHeight * bytesPerLine);
|
|
||||||
this._lines -= currHeight;
|
this._lines -= currHeight;
|
||||||
if (this._lines > 0) {
|
if (this._lines > 0) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -76,12 +76,8 @@ export default class TightDecoder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rQi = sock.rQi;
|
let pixel = sock.rQshiftBytes(3);
|
||||||
const rQ = sock.rQ;
|
display.fillRect(x, y, width, height, pixel, false);
|
||||||
|
|
||||||
display.fillRect(x, y, width, height,
|
|
||||||
[rQ[rQi], rQ[rQi + 1], rQ[rQi + 2]], false);
|
|
||||||
sock.rQskipBytes(3);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,22 +94,6 @@ export default class Websock {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
get sQ() {
|
|
||||||
return this._sQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
get rQ() {
|
|
||||||
return this._rQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
get rQi() {
|
|
||||||
return this._rQi;
|
|
||||||
}
|
|
||||||
|
|
||||||
set rQi(val) {
|
|
||||||
this._rQi = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Receive Queue
|
// Receive Queue
|
||||||
get rQlen() {
|
get rQlen() {
|
||||||
return this._rQlen - this._rQi;
|
return this._rQlen - this._rQi;
|
||||||
|
|
|
@ -19,13 +19,13 @@ 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.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.rQi = 1;
|
sock._rQi = 1;
|
||||||
|
|
||||||
expect(sock.rQlen).to.equal(RQ_TEMPLATE.length - 1);
|
expect(sock.rQlen).to.equal(RQ_TEMPLATE.length - 1);
|
||||||
});
|
});
|
||||||
|
@ -72,8 +72,8 @@ describe('Websock', function () {
|
||||||
|
|
||||||
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 befLen = sock.rQlen;
|
const befLen = sock._rQlen;
|
||||||
const befRQi = sock.rQi;
|
const befRQi = 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, befRQi, 3))));
|
expect(shifted).to.equal(String.fromCharCode.apply(null, Array.prototype.slice.call(new Uint8Array(RQ_TEMPLATE.buffer, befRQi, 3))));
|
||||||
|
@ -112,8 +112,8 @@ describe('Websock', function () {
|
||||||
|
|
||||||
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 befLen = sock.rQlen;
|
const befLen = sock._rQlen;
|
||||||
const befRQi = sock.rQi;
|
const befRQi = 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, befRQi, 3));
|
expect(shifted).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, befRQi, 3));
|
||||||
|
@ -128,7 +128,7 @@ describe('Websock', function () {
|
||||||
|
|
||||||
describe('rQpeekBytes', function () {
|
describe('rQpeekBytes', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
sock.rQi = 0;
|
sock._rQi = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not modify the receive queue', function () {
|
it('should not modify 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.rQi = 1;
|
sock._rQi = 1;
|
||||||
expect(sock.rQpeekBytes(2)).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 1, 2));
|
expect(sock.rQpeekBytes(2)).to.array.equal(new Uint8Array(RQ_TEMPLATE.buffer, 1, 2));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('rQwait', function () {
|
describe('rQwait', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
sock.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.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.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.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.rQi = 5;
|
sock._rQi = 5;
|
||||||
sock.rQwait('hi', 1, 6);
|
sock.rQwait('hi', 1, 6);
|
||||||
expect(sock.rQi).to.equal(5);
|
expect(sock._rQi).to.equal(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -461,52 +461,52 @@ describe('Websock', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compact the receive queue when a message handler empties it', function () {
|
it('should compact the receive queue when a message handler empties it', function () {
|
||||||
sock._eventHandlers.message = () => { sock.rQi = sock._rQlen; };
|
sock._eventHandlers.message = () => { sock._rQi = sock._rQlen; };
|
||||||
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.rQi = 6;
|
sock._rQi = 6;
|
||||||
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._recvMessage(msg);
|
sock._recvMessage(msg);
|
||||||
expect(sock._rQlen).to.equal(0);
|
expect(sock._rQlen).to.equal(0);
|
||||||
expect(sock.rQi).to.equal(0);
|
expect(sock._rQi).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compact the receive queue when we reach the end of the buffer', function () {
|
it('should compact the receive queue when we reach the end of the buffer', function () {
|
||||||
sock._rQ = new Uint8Array(20);
|
sock._rQ = new Uint8Array(20);
|
||||||
sock._rQbufferSize = 20;
|
sock._rQbufferSize = 20;
|
||||||
sock._rQlen = 20;
|
sock._rQlen = 20;
|
||||||
sock.rQi = 10;
|
sock._rQi = 10;
|
||||||
const msg = { data: new Uint8Array([1, 2]).buffer };
|
const msg = { data: new Uint8Array([1, 2]).buffer };
|
||||||
sock._mode = 'binary';
|
sock._mode = 'binary';
|
||||||
sock._recvMessage(msg);
|
sock._recvMessage(msg);
|
||||||
expect(sock._rQlen).to.equal(12);
|
expect(sock._rQlen).to.equal(12);
|
||||||
expect(sock.rQi).to.equal(0);
|
expect(sock._rQi).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should automatically resize the receive queue if the incoming message is larger than the buffer', function () {
|
it('should automatically resize the receive queue if the incoming message is larger than the buffer', function () {
|
||||||
sock._rQ = new Uint8Array(20);
|
sock._rQ = new Uint8Array(20);
|
||||||
sock._rQlen = 0;
|
sock._rQlen = 0;
|
||||||
sock.rQi = 0;
|
sock._rQi = 0;
|
||||||
sock._rQbufferSize = 20;
|
sock._rQbufferSize = 20;
|
||||||
const msg = { data: new Uint8Array(30).buffer };
|
const msg = { data: new Uint8Array(30).buffer };
|
||||||
sock._mode = 'binary';
|
sock._mode = 'binary';
|
||||||
sock._recvMessage(msg);
|
sock._recvMessage(msg);
|
||||||
expect(sock._rQlen).to.equal(30);
|
expect(sock._rQlen).to.equal(30);
|
||||||
expect(sock.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
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should automatically resize the receive queue if the incoming message is larger than 1/8th of the buffer and we reach the end of the buffer', function () {
|
it('should automatically resize the receive queue if the incoming message is larger than 1/8th of the buffer and we reach the end of the buffer', function () {
|
||||||
sock._rQ = new Uint8Array(20);
|
sock._rQ = new Uint8Array(20);
|
||||||
sock._rQlen = 16;
|
sock._rQlen = 16;
|
||||||
sock.rQi = 16;
|
sock._rQi = 16;
|
||||||
sock._rQbufferSize = 20;
|
sock._rQbufferSize = 20;
|
||||||
const msg = { data: new Uint8Array(6).buffer };
|
const msg = { data: new Uint8Array(6).buffer };
|
||||||
sock._mode = 'binary';
|
sock._mode = 'binary';
|
||||||
sock._recvMessage(msg);
|
sock._recvMessage(msg);
|
||||||
expect(sock._rQlen).to.equal(6);
|
expect(sock._rQlen).to.equal(6);
|
||||||
expect(sock.rQi).to.equal(0);
|
expect(sock._rQi).to.equal(0);
|
||||||
expect(sock._rQ.length).to.equal(48);
|
expect(sock._rQ.length).to.equal(48);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue