Add support for fences
We don't actually use these, but servers may require this for other features.
This commit is contained in:
parent
37195e4b5e
commit
3df1326239
|
@ -56,7 +56,8 @@ var RFB;
|
||||||
['last_rect', -224 ],
|
['last_rect', -224 ],
|
||||||
['Cursor', -239 ],
|
['Cursor', -239 ],
|
||||||
['ExtendedDesktopSize', -308 ],
|
['ExtendedDesktopSize', -308 ],
|
||||||
['xvp', -309 ]
|
['xvp', -309 ],
|
||||||
|
['Fence', -312 ]
|
||||||
];
|
];
|
||||||
|
|
||||||
this._encHandlers = {};
|
this._encHandlers = {};
|
||||||
|
@ -70,6 +71,8 @@ var RFB;
|
||||||
this._disconnTimer = null; // disconnection timer
|
this._disconnTimer = null; // disconnection timer
|
||||||
this._msgTimer = null; // queued handle_msg timer
|
this._msgTimer = null; // queued handle_msg timer
|
||||||
|
|
||||||
|
this._supportsFence = false;
|
||||||
|
|
||||||
// Frame buffer update state
|
// Frame buffer update state
|
||||||
this._FBU = {
|
this._FBU = {
|
||||||
rects: 0,
|
rects: 0,
|
||||||
|
@ -1041,6 +1044,42 @@ var RFB;
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_handle_server_fence_msg: function() {
|
||||||
|
if (this._sock.rQwait("ServerFence header", 8, 1)) { return false; }
|
||||||
|
this._sock.rQskipBytes(3); // Padding
|
||||||
|
var flags = this._sock.rQshift32();
|
||||||
|
var length = this._sock.rQshift8();
|
||||||
|
|
||||||
|
if (this._sock.rQwait("ServerFence payload", length, 9)) { return false; }
|
||||||
|
var payload = this._sock.rQshiftStr(length); // FIXME: 64 bytes max
|
||||||
|
|
||||||
|
this._supportsFence = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fence flags
|
||||||
|
*
|
||||||
|
* (1<<0) - BlockBefore
|
||||||
|
* (1<<1) - BlockAfter
|
||||||
|
* (1<<2) - SyncNext
|
||||||
|
* (1<<31) - Request
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(flags & (1<<31))) {
|
||||||
|
return this._fail("Unexpected fence response");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out unsupported flags
|
||||||
|
// FIXME: support syncNext
|
||||||
|
flags &= (1<<0) | (1<<1);
|
||||||
|
|
||||||
|
// BlockBefore and BlockAfter are automatically handled by
|
||||||
|
// the fact that we process each incoming message
|
||||||
|
// synchronuosly.
|
||||||
|
RFB.messages.clientFence(this._sock, flags, payload);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
_handle_xvp_msg: function () {
|
_handle_xvp_msg: function () {
|
||||||
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.rQskip8(); // Padding
|
||||||
|
@ -1092,6 +1131,9 @@ var RFB;
|
||||||
case 3: // ServerCutText
|
case 3: // ServerCutText
|
||||||
return this._handle_server_cut_text();
|
return this._handle_server_cut_text();
|
||||||
|
|
||||||
|
case 248: // ServerFence
|
||||||
|
return this._handle_server_fence_msg();
|
||||||
|
|
||||||
case 250: // XVP
|
case 250: // XVP
|
||||||
return this._handle_xvp_msg();
|
return this._handle_xvp_msg();
|
||||||
|
|
||||||
|
@ -1350,6 +1392,33 @@ var RFB;
|
||||||
sock.flush();
|
sock.flush();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clientFence: function (sock, flags, payload) {
|
||||||
|
var buff = sock._sQ;
|
||||||
|
var offset = sock._sQlen;
|
||||||
|
|
||||||
|
buff[offset] = 248; // msg-type
|
||||||
|
|
||||||
|
buff[offset + 1] = 0; // padding
|
||||||
|
buff[offset + 2] = 0; // padding
|
||||||
|
buff[offset + 3] = 0; // padding
|
||||||
|
|
||||||
|
buff[offset + 4] = flags >> 24; // flags
|
||||||
|
buff[offset + 5] = flags >> 16;
|
||||||
|
buff[offset + 6] = flags >> 8;
|
||||||
|
buff[offset + 7] = flags;
|
||||||
|
|
||||||
|
var n = payload.length;
|
||||||
|
|
||||||
|
buff[offset + 8] = n; // length
|
||||||
|
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
buff[offset + 9 + i] = payload.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
sock._sQlen += 9 + n;
|
||||||
|
sock.flush();
|
||||||
|
},
|
||||||
|
|
||||||
pixelFormat: function (sock, bpp, depth, true_color) {
|
pixelFormat: function (sock, bpp, depth, true_color) {
|
||||||
var buff = sock._sQ;
|
var buff = sock._sQ;
|
||||||
var offset = sock._sQlen;
|
var offset = sock._sQlen;
|
||||||
|
|
|
@ -1705,6 +1705,31 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||||
expect(client.get_onBell()).to.have.been.calledOnce;
|
expect(client.get_onBell()).to.have.been.calledOnce;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respond correctly to ServerFence', function () {
|
||||||
|
var expected_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function() {}};
|
||||||
|
var incoming_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function() {}};
|
||||||
|
|
||||||
|
var payload = "foo\x00ab9";
|
||||||
|
|
||||||
|
// ClientFence and ServerFence are identical in structure
|
||||||
|
RFB.messages.clientFence(expected_msg, (1<<0) | (1<<1), payload);
|
||||||
|
RFB.messages.clientFence(incoming_msg, 0xffffffff, payload);
|
||||||
|
|
||||||
|
client._sock._websocket._receive_data(incoming_msg._sQ);
|
||||||
|
|
||||||
|
expect(client._sock).to.have.sent(expected_msg._sQ);
|
||||||
|
|
||||||
|
expected_msg._sQlen = 0;
|
||||||
|
incoming_msg._sQlen = 0;
|
||||||
|
|
||||||
|
RFB.messages.clientFence(expected_msg, (1<<0), payload);
|
||||||
|
RFB.messages.clientFence(incoming_msg, (1<<0) | (1<<31), payload);
|
||||||
|
|
||||||
|
client._sock._websocket._receive_data(incoming_msg._sQ);
|
||||||
|
|
||||||
|
expect(client._sock).to.have.sent(expected_msg._sQ);
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail on an unknown message type', function () {
|
it('should fail on an unknown message type', function () {
|
||||||
client._sock._websocket._receive_data(new Uint8Array([87]));
|
client._sock._websocket._receive_data(new Uint8Array([87]));
|
||||||
expect(client._rfb_state).to.equal('failed');
|
expect(client._rfb_state).to.equal('failed');
|
||||||
|
|
Loading…
Reference in New Issue