Fix jsdoc, add missing documentation.
[guacamole-common-js.git] / src / main / resources / tunnel.js
index 5b5a167..4f75ea3 100644 (file)
  *
  * ***** END LICENSE BLOCK ***** */
 
-// Guacamole namespace
+/**
+ * Namespace for all Guacamole JavaScript objects.
+ * @namespace
+ */
 var Guacamole = Guacamole || {};
 
 /**
@@ -104,6 +107,7 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
 
     /**
      * Reference to this HTTP tunnel.
+     * @private
      */
     var tunnel = this;
 
@@ -142,6 +146,7 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
          * Converts the given value to a length/string pair for use as an
          * element in a Guacamole instruction.
          * 
+         * @private
          * @param value The value to convert.
          * @return {String} The converted value. 
          */
@@ -181,8 +186,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 +208,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 +314,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 +456,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
@@ -447,17 +489,20 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
 
     /**
      * Reference to this WebSocket tunnel.
+     * @private
      */
     var tunnel = this;
 
     /**
      * The WebSocket used by this tunnel.
+     * @private
      */
     var socket = null;
 
     /**
      * The WebSocket protocol corresponding to the protocol used for the current
      * location.
+     * @private
      */
     var ws_protocol = {
         "http:":  "ws:",
@@ -531,6 +576,7 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
          * Converts the given value to a length/string pair for use as an
          * element in a Guacamole instruction.
          * 
+         * @private
          * @param value The value to convert.
          * @return {String} The converted value. 
          */
@@ -663,23 +709,27 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
 
     /**
      * Reference to this chained tunnel.
+     * @private
      */
     var chained_tunnel = this;
 
     /**
      * The currently wrapped tunnel, if any.
+     * @private
      */
     var current_tunnel = null;
 
     /**
      * Data passed in via connect(), to be used for
      * wrapped calls to other tunnels' connect() functions.
+     * @private
      */
     var connect_data;
 
     /**
      * Array of all tunnels passed to this ChainedTunnel through the
      * constructor arguments.
+     * @private
      */
     var tunnels = [];
 
@@ -688,10 +738,19 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
         tunnels.push(arguments[i]);
 
     /**
-     * Sets the current tunnel
+     * Sets the current tunnel.
+     * 
+     * @private
+     * @param {Guacamole.Tunnel} tunnel The tunnel to set as the current tunnel.
      */
     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;
@@ -729,8 +788,19 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
 
         };
 
-        // 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);
+            
+        }
+
 
     }