Change "Connection does not exist" to more user-friendly error.
[guacamole-common-js.git] / src / main / resources / tunnel.js
index 3a0a481..87155eb 100644 (file)
@@ -181,8 +181,17 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
 
             // Once response received, send next queued event.
             message_xmlhttprequest.onreadystatechange = function() {
-                if (message_xmlhttprequest.readyState == 4)
-                    sendPendingMessages();
+                if (message_xmlhttprequest.readyState == 4) {
+
+                    // If an error occurs during send, handle it
+                    if (message_xmlhttprequest.status != 200)
+                        handleHTTPTunnelError(message_xmlhttprequest);
+
+                    // Otherwise, continue the send loop
+                    else
+                        sendPendingMessages();
+
+                }
             }
 
             message_xmlhttprequest.send(outputMessageBuffer);
@@ -194,6 +203,49 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
 
     }
 
+    function getHTTPTunnelErrorMessage(xmlhttprequest) {
+
+        var status = xmlhttprequest.status;
+
+        // Special cases
+        if (status == 0)   return "Disconnected";
+        if (status == 200) return "Success";
+        if (status == 403) return "Unauthorized";
+        if (status == 404) return "Connection closed"; /* While it may be more
+                                                        * accurate to say the
+                                                        * connection does not
+                                                        * exist, it is confusing
+                                                        * to the user.
+                                                        * 
+                                                        * In general, this error
+                                                        * will only happen when
+                                                        * the tunnel does not
+                                                        * exist, which happens
+                                                        * after the connection
+                                                        * is closed and the
+                                                        * tunnel is detached.
+                                                        */
+        // Internal server errors
+        if (status >= 500 && status <= 599) return "Server error";
+
+        // Otherwise, unknown
+        return "Unknown error";
+
+    }
+
+    function handleHTTPTunnelError(xmlhttprequest) {
+
+        // Get error message
+        var message = getHTTPTunnelErrorMessage(xmlhttprequest);
+
+        // Call error handler
+        if (tunnel.onerror) tunnel.onerror(message);
+
+        // Finish
+        tunnel.disconnect();
+
+    }
+
 
     function handleResponse(xmlhttprequest) {
 
@@ -257,17 +309,7 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
 
                 // Halt on error during request
                 else if (xmlhttprequest.status != 200) {
-
-                    // Get error message (if any)
-                    var message = xmlhttprequest.getResponseHeader("X-Guacamole-Error-Message");
-                    if (!message)
-                        message = "Internal server error";
-
-                    // Call error handler
-                    if (tunnel.onerror) tunnel.onerror(message);
-
-                    // Finish
-                    tunnel.disconnect();
+                    handleHTTPTunnelError(xmlhttprequest);
                     return;
                 }
 
@@ -409,13 +451,8 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
 
         // If failure, throw error
         if (connect_xmlhttprequest.status != 200) {
-
-            var message = connect_xmlhttprequest.getResponseHeader("X-Guacamole-Error-Message");
-            if (!message)
-                message = "Internal error";
-
+            var message = getHTTPTunnelErrorMessage(connect_xmlhttprequest);
             throw new Error(message);
-
         }
 
         // Get UUID from response
@@ -648,12 +685,39 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
 Guacamole.WebSocketTunnel.prototype = new Guacamole.Tunnel();
 
 
-Guacamole.ChainedTunnel = function() {
+/**
+ * Guacamole Tunnel which cycles between all specified tunnels until
+ * no tunnels are left. Another tunnel is used if an error occurs but
+ * no instructions have been received. If an instruction has been
+ * received, or no tunnels remain, the error is passed directly out
+ * through the onerror handler (if defined).
+ * 
+ * @constructor
+ * @augments Guacamole.Tunnel
+ * @param {...} tunnel_chain The tunnels to use, in order of priority.
+ */
+Guacamole.ChainedTunnel = function(tunnel_chain) {
 
+    /**
+     * Reference to this chained tunnel.
+     */
     var chained_tunnel = this;
+
+    /**
+     * The currently wrapped tunnel, if any.
+     */
     var current_tunnel = null;
 
+    /**
+     * Data passed in via connect(), to be used for
+     * wrapped calls to other tunnels' connect() functions.
+     */
     var connect_data;
+
+    /**
+     * Array of all tunnels passed to this ChainedTunnel through the
+     * constructor arguments.
+     */
     var tunnels = [];
 
     // Load all tunnels into array
@@ -665,6 +729,12 @@ Guacamole.ChainedTunnel = function() {
      */
     function attach(tunnel) {
 
+        // Clear handlers of current tunnel, if any
+        if (current_tunnel) {
+            current_tunnel.onerror = null;
+            current_tunnel.oninstruction = null;
+        }
+
         // Set own functions to tunnel's functions
         chained_tunnel.disconnect    = tunnel.disconnect;
         chained_tunnel.sendMessage   = tunnel.sendMessage;
@@ -702,8 +772,19 @@ Guacamole.ChainedTunnel = function() {
 
         };
 
-        // Attempt connection
-        current_tunnel.connect(connect_data);
+        try {
+            
+            // Attempt connection
+            current_tunnel.connect(connect_data);
+            
+        }
+        catch (e) {
+            
+            // Call error handler of current tunnel on error
+            current_tunnel.onerror(e.message);
+            
+        }
+
 
     }
 
@@ -725,8 +806,6 @@ Guacamole.ChainedTunnel = function() {
 
     };
     
-    this.onerror = null;
-
 };
 
 Guacamole.ChainedTunnel.prototype = new Guacamole.Tunnel();