diff options
author | samhed <samuel@cendio.se> | 2016-06-02 16:00:33 +0200 |
---|---|---|
committer | samhed <samuel@cendio.se> | 2016-06-03 16:37:19 +0200 |
commit | 3df13262394515efe5877ce33fd0dbdf35e1b743 (patch) | |
tree | 582a6ded51f88e67f0a74a40acab5faa61f81f7f | |
parent | 37195e4b5e776d1ce19a65ba72009536de7dcd67 (diff) | |
download | novnc-3df13262394515efe5877ce33fd0dbdf35e1b743.tar.gz |
Add support for fences
We don't actually use these, but servers may require this for other
features.
-rw-r--r-- | include/rfb.js | 71 | ||||
-rw-r--r-- | tests/test.rfb.js | 25 |
2 files changed, 95 insertions, 1 deletions
diff --git a/include/rfb.js b/include/rfb.js index 14e0aa6..71672ff 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -56,7 +56,8 @@ var RFB; ['last_rect', -224 ], ['Cursor', -239 ], ['ExtendedDesktopSize', -308 ], - ['xvp', -309 ] + ['xvp', -309 ], + ['Fence', -312 ] ]; this._encHandlers = {}; @@ -70,6 +71,8 @@ var RFB; this._disconnTimer = null; // disconnection timer this._msgTimer = null; // queued handle_msg timer + this._supportsFence = false; + // Frame buffer update state this._FBU = { rects: 0, @@ -1041,6 +1044,42 @@ var RFB; 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 () { if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; } this._sock.rQskip8(); // Padding @@ -1092,6 +1131,9 @@ var RFB; case 3: // ServerCutText return this._handle_server_cut_text(); + case 248: // ServerFence + return this._handle_server_fence_msg(); + case 250: // XVP return this._handle_xvp_msg(); @@ -1350,6 +1392,33 @@ var RFB; 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) { var buff = sock._sQ; var offset = sock._sQlen; diff --git a/tests/test.rfb.js b/tests/test.rfb.js index a0fdf8f..be6aa1b 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1705,6 +1705,31 @@ describe('Remote Frame Buffer Protocol Client', function() { 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 () { client._sock._websocket._receive_data(new Uint8Array([87])); expect(client._rfb_state).to.equal('failed'); |