};
Guacamole.HTTPTunnel.prototype = new Guacamole.Tunnel();
+
+
+/**
+ * Guacamole Tunnel implemented over WebSocket via XMLHttpRequest.
+ *
+ * @constructor
+ * @augments Guacamole.Tunnel
+ * @param {String} tunnelURL The URL of the WebSocket tunneling service.
+ */
+Guacamole.WebSocketTunnel = function(tunnelURL) {
+
+ /**
+ * Reference to this WebSocket tunnel.
+ */
+ var tunnel = this;
+
+ /**
+ * The WebSocket used by this tunnel.
+ */
+ var socket = null;
+
+ /**
+ * The WebSocket protocol corresponding to the protocol used for the current
+ * location.
+ */
+ var ws_protocol = {
+ "http:": "ws:",
+ "https:": "wss:"
+ };
+
+ var STATE_IDLE = 0;
+ var STATE_CONNECTED = 1;
+ var STATE_DISCONNECTED = 2;
+
+ var currentState = STATE_IDLE;
+
+ // Transform current URL to WebSocket URL
+
+ // If not already a websocket URL
+ if ( tunnelURL.substring(0, 3) != "ws:"
+ && tunnelURL.substring(0, 4) != "wss:") {
+
+ var protocol = ws_protocol[window.location.protocol];
+
+ // If absolute URL, convert to absolute WS URL
+ if (tunnelURL.substring(0, 1) == "/")
+ tunnelURL =
+ protocol
+ + "//" + window.location.host
+ + tunnelURL;
+
+ // Otherwise, construct absolute from relative URL
+ else {
+
+ // Get path from pathname
+ var slash = window.location.pathname.lastIndexOf("/");
+ var path = window.location.pathname.substring(0, slash + 1);
+
+ // Construct absolute URL
+ tunnelURL =
+ protocol
+ + "//" + window.location.host
+ + path
+ + tunnelURL;
+
+ }
+
+ }
+
+ this.sendMessage = function(message) {
+
+ // Do not attempt to send messages if not connected
+ if (currentState != STATE_CONNECTED)
+ return;
+
+ socket.send(message);
+
+ };
+
+ this.connect = function(data) {
+
+ // Connect socket
+ socket = new WebSocket(tunnelURL + "?" + data, "guacamole");
+
+ socket.onopen = function(event) {
+ currentState = STATE_CONNECTED;
+ };
+
+ socket.onmessage = function(event) {
+
+ var message = event.data;
+
+ var instructions = message.split(";");
+ for (var i=0; i<instructions.length; i++) {
+
+ var instruction = instructions[i];
+
+ var opcodeEnd = instruction.indexOf(":");
+ if (opcodeEnd == -1)
+ opcodeEnd = instruction.length;
+
+ var opcode = instruction.substring(0, opcodeEnd);
+ var parameters = instruction.substring(opcodeEnd+1).split(",");
+
+ if (tunnel.oninstruction)
+ tunnel.oninstruction(opcode, parameters);
+
+ }
+
+ };
+
+ };
+
+ this.disconnect = function() {
+ currentState = STATE_DISCONNECTED;
+ socket.close();
+ };
+
+};
+
+Guacamole.WebSocketTunnel.prototype = new Guacamole.Tunnel();
+