]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Add support for fences
authorsamhed <samuel@cendio.se>
Thu, 2 Jun 2016 14:00:33 +0000 (16:00 +0200)
committersamhed <samuel@cendio.se>
Fri, 3 Jun 2016 14:37:19 +0000 (16:37 +0200)
We don't actually use these, but servers may require this for other
features.

include/rfb.js
tests/test.rfb.js

index 14e0aa62072720fb604da9ce255d9af6476c939d..71672ffe1aed5cc67cfe38997d0fbaeb59d3d6a7 100644 (file)
@@ -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;
index a0fdf8f2248dca59846a634f7bda31645469f075..be6aa1b2d52acb270c241d27b81f13e834307d56 100644 (file)
@@ -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');