From ff36b1270b04b706fea43f3ac94508c230cd86a7 Mon Sep 17 00:00:00 2001
From: Joel Martin <github@martintribe.org>
Date: Thu, 23 Sep 2010 09:39:24 -0500
Subject: [PATCH] Refactor settings object, add connectTimeout setting.

- include/util.js: Add type and desc field to conf_default routine.
  Make comment descriptions of settings into desc parameters that can
  be queried. Also, use set_FOO in conf_default to set or coerce the
  current setting so that we always have the right type for the value.

- include/rfb.js, include/default_config.js: add connectTimeout
  setting to address situations with slow connections that may need
  more than 2 seconds.
---
 include/canvas.js           | 24 ++++++++++--------
 include/default_controls.js |  7 ++++++
 include/plain.css           |  5 +++-
 include/rfb.js              | 50 ++++++++++++++++++-------------------
 include/util.js             | 19 ++++++++++----
 5 files changed, 62 insertions(+), 43 deletions(-)

diff --git a/include/canvas.js b/include/canvas.js
index 3b9cde5..41d9459 100644
--- a/include/canvas.js
+++ b/include/canvas.js
@@ -31,18 +31,20 @@ var that           = {},         // Public API interface
     c_mouseMove    = null;
 
 
-// Capability settings, default can be overridden
-Util.conf_default(conf, that, 'prefer_js', null);
-Util.conf_default(conf, that, 'cursor_uri', null);
-
 // Configuration settings
-Util.conf_default(conf, that, 'target', null);
-// Area that traps keyboard input
-Util.conf_default(conf, that, 'focusContainer', document);
-Util.conf_default(conf, that, 'true_color', true);
-Util.conf_default(conf, that, 'focused', true);
-Util.conf_default(conf, that, 'colourMap', []);
-Util.conf_default(conf, that, 'scale', 1);
+function cdef(v, type, defval, desc) {
+    Util.conf_default(conf, that, v, type, defval, desc); }
+
+// Capability settings, default can be overridden
+cdef('prefer_js',      'raw', null, 'Prefer Javascript over canvas methods');
+cdef('cursor_uri',     'raw', null, 'Can we render cursor using data URI');
+
+cdef('target',         'dom',  null, 'Canvas element for VNC viewport');
+cdef('focusContainer', 'dom',  document, 'DOM element that traps keyboard input');
+cdef('true_color',     'bool', true, 'Request true color pixel data');
+cdef('focused',        'bool', true, 'Capture and send key strokes');
+cdef('colourMap',      'raw',  [], 'Colour map array (not true color)');
+cdef('scale',          'float', 1, 'VNC viewport scale factor');
 
 // Override some specific getters/setters
 that.set_prefer_js = function(val) {
diff --git a/include/default_controls.js b/include/default_controls.js
index 7840e43..2864ee7 100644
--- a/include/default_controls.js
+++ b/include/default_controls.js
@@ -49,6 +49,8 @@ load: function(target) {
     html += '                type="checkbox" checked> True Color</li>';
     html += '            <li><input id="VNC_cursor"';
     html += '                type="checkbox"> Local Cursor</li>';
+    html += '            <li><input id="VNC_connectTimeout"';
+    html += '                type="input"> Connect Timeout (s)</li>';
     html += '            <hr>';
 
     // Stylesheet selection dropdown
@@ -113,6 +115,7 @@ load: function(target) {
     DC.initSetting('encrypt', false);
     DC.initSetting('true_color', true);
     DC.initSetting('cursor', false);
+    DC.initSetting('connectTimeout', 2);
 
     DC.rfb = RFB({'target': 'VNC_canvas',
                   'updateState': DC.updateState,
@@ -215,6 +218,7 @@ clickSettingsMenu: function() {
             DC.updateSetting('cursor', false);
             $('VNC_cursor').disabled = true;
         }
+        DC.updateSetting('connectTimeout');
         DC.updateSetting('stylesheet');
         DC.updateSetting('logging');
 
@@ -245,6 +249,7 @@ settingsDisabled: function(disabled, rfb) {
         DefaultControls.updateSetting('cursor', false);
         $('VNC_cursor').disabled = true;
     }
+    $('VNC_connectTimeout').disabled = disabled;
     //Util.Debug("<< settingsDisabled");
 },
 
@@ -257,6 +262,7 @@ settingsApply: function() {
     if (DC.rfb.get_canvas().get_cursor_uri()) {
         DC.saveSetting('cursor');
     }
+    DC.saveSetting('connectTimeout');
     DC.saveSetting('stylesheet');
     DC.saveSetting('logging');
 
@@ -357,6 +363,7 @@ connect: function() {
     DC.rfb.set_encrypt(DC.getSetting('encrypt'));
     DC.rfb.set_true_color(DC.getSetting('true_color'));
     DC.rfb.set_local_cursor(DC.getSetting('cursor'));
+    DC.rfb.set_connectTimeout(DC.getSetting('connectTimeout'));
 
     DC.rfb.connect(host, port, password);
 },
diff --git a/include/plain.css b/include/plain.css
index c8d853b..d8ee942 100644
--- a/include/plain.css
+++ b/include/plain.css
@@ -22,8 +22,11 @@
 }
 #VNC_encrypt {
 }
+#VNC_connectTimeout {
+    width: 30;
+}
 #VNC_connect_button {
-    width: 100px;
+    width: 110px;
 }
 
 #VNC_status_bar td {
diff --git a/include/rfb.js b/include/rfb.js
index d0f59b8..f904936 100644
--- a/include/rfb.js
+++ b/include/rfb.js
@@ -127,31 +127,27 @@ var that           = {},         // Public API interface
 //
 // Configuration settings
 //
+function cdef(v, type, defval, desc) {
+    Util.conf_default(conf, that, v, type, defval, desc); }
 
-// VNC viewport rendering Canvas
-Util.conf_default(conf, that, 'target', 'VNC_canvas');
-// Area that traps keyboard input
-Util.conf_default(conf, that, 'focusContainer', document);
+cdef('target',         'str', 'VNC_canvas', 'VNC viewport rendering Canvas');
+cdef('focusContainer', 'dom', document, 'Area that traps keyboard input');
 
-Util.conf_default(conf, that, 'encrypt',        false, true);
-Util.conf_default(conf, that, 'true_color',     true, true);
-Util.conf_default(conf, that, 'local_cursor',   false, true);
+cdef('encrypt',        'bool', false, 'Use TLS/SSL/wss encryption');
+cdef('true_color',     'bool', true,  'Request true color pixel data');
+cdef('local_cursor',   'bool', false, 'Request locally rendered cursor');
 
-// time to wait for connection
-Util.conf_default(conf, that, 'connectTimeout', 2000);
-// time to wait for disconnection
-Util.conf_default(conf, that, 'disconnectTimeout', 3000);
-// frequency to check for send/receive
-Util.conf_default(conf, that, 'check_rate',     217);
-// frequency to send frameBufferUpdate requests
-Util.conf_default(conf, that, 'fbu_req_rate',   1413);
+cdef('connectTimeout',    'int', 2,    'Time (s) to wait for connection');
+cdef('disconnectTimeout', 'int', 3,    'Time (s) to wait for disconnection');
+cdef('check_rate',        'int', 217,  'Timing (ms) of send/receive check');
+cdef('fbu_req_rate',      'int', 1413, 'Timing (ms) of frameBufferUpdate requests');
 
-// state update callback
-Util.conf_default(conf, that, 'updateState', function () {
-        Util.Debug(">> externalUpdateState stub"); });
-// clipboard contents received callback
-Util.conf_default(conf, that, 'clipboardReceive', function () {
-        Util.Debug(">> clipboardReceive stub"); });
+cdef('updateState',
+     'func', function() { Util.Debug("updateState stub"); },
+     'callback: state update');
+cdef('clipboardReceive',
+     'func', function() { Util.Debug("clipboardReceive stub"); },
+     'callback: clipboard contents received');
 
 
 // Override/add some specific getters/setters
@@ -426,7 +422,7 @@ updateState = function(state, statusMsg) {
         
         connTimer = setTimeout(function () {
                 updateState('failed', "Connect timeout");
-            }, conf.connectTimeout);
+            }, conf.connectTimeout * 1000);
 
         init_vars();
         init_ws();
@@ -437,9 +433,11 @@ updateState = function(state, statusMsg) {
 
     case 'disconnect':
 
-        disconnTimer = setTimeout(function () {
-                updateState('failed', "Disconnect timeout");
-            }, conf.disconnectTimeout);
+        if (! test_mode) {
+            disconnTimer = setTimeout(function () {
+                    updateState('failed', "Disconnect timeout");
+                }, conf.disconnectTimeout * 1000);
+        }
 
         // WebSocket.onclose transitions to 'disconnected'
         break;
@@ -526,7 +524,7 @@ function handle_message() {
 }
 
 recv_message = function(e) {
-    //Util.Debug(">> recv_message");
+    //Util.Debug(">> recv_message: " + e.data.length);
 
     try {
         decode_message(e.data);
diff --git a/include/util.js b/include/util.js
index b67391d..91883f4 100644
--- a/include/util.js
+++ b/include/util.js
@@ -131,10 +131,9 @@ Util.getQueryVar = function(name, defVal) {
 };
 
 // Set defaults for Crockford style function namespaces
-Util.conf_default = function(cfg, api, v, val, force_bool) {
-    if (typeof cfg[v] === 'undefined') {
-        cfg[v] = val;
-    }
+Util.conf_default = function(cfg, api, v, type, defval, desc) {
+    // Description
+    api['get_' + v + '_desc'] = desc;
     // Default getter
     if (typeof api['get_' + v] === 'undefined') {
         api['get_' + v] = function () {
@@ -144,16 +143,26 @@ Util.conf_default = function(cfg, api, v, val, force_bool) {
     // Default setter
     if (typeof api['set_' + v] === 'undefined') {
         api['set_' + v] = function (val) {
-                if (force_bool) {
+                if (type in {'boolean':1, 'bool':1}) {
                     if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
                         val = false;
                     } else {
                         val = true;
                     }
+                } else if (type in {'integer':1, 'int':1}) {
+                    val = parseInt(val, 10);
                 }
                 cfg[v] = val;
             };
     }
+
+    if (typeof cfg[v] === 'undefined') {
+        // Set to default
+        api['set_' + v](defval);
+    } else {
+        // Coerce existing setting to the right type
+        api['set_' + v](cfg[v]);
+    }
 };
 
 
-- 
2.18.1