Merge 1.3.0 changes back to master.
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
index 6687eb3..44b65bf 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
@@ -201,87 +201,52 @@
ModeledConnectionGroup connectionGroup);
/**
- * Returns a guacamole configuration containing the protocol and parameters
- * from the given connection. If the ID of an active connection is
- * provided, that connection will be joined instead of starting a new
- * primary connection. If tokens are used in the connection parameter
- * values, credentials from the given user will be substituted
- * appropriately.
- *
- * @param user
- * The user whose credentials should be used if necessary.
+ * Returns a GuacamoleConfiguration which connects to the given connection.
+ * If the ID of an active connection is provided, that active connection
+ * will be joined rather than establishing an entirely new connection. If
+ * a sharing profile is provided, the parameters associated with that
+ * sharing profile will be used to define the access provided to the user
+ * accessing the shared connection.
*
* @param connection
- * The connection whose protocol and parameters should be added to the
- * returned configuration.
+ * The connection that the user is connecting to.
*
* @param connectionID
- * The ID of the active connection to be joined, as returned by guacd,
- * or null if a new primary connection should be established.
- *
- * @return
- * A GuacamoleConfiguration containing the protocol and parameters from
- * the given connection.
- */
- private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
- ModeledConnection connection, String connectionID) {
-
- // Generate configuration from available data
- GuacamoleConfiguration config = new GuacamoleConfiguration();
-
- // Join existing active connection, if any
- if (connectionID != null)
- config.setConnectionID(connectionID);
-
- // Set protocol from connection if not joining an active connection
- else {
- ConnectionModel model = connection.getModel();
- config.setProtocol(model.getProtocol());
- }
-
- // Set parameters from associated data
- Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
- for (ConnectionParameterModel parameter : parameters)
- config.setParameter(parameter.getName(), parameter.getValue());
-
- return config;
-
- }
-
- /**
- * Returns a guacamole configuration which joins the active connection
- * having the given ID, using the provided sharing profile to restrict the
- * access provided to the user accessing the shared connection. If tokens
- * are used in the connection parameter values of the sharing profile,
- * credentials from the given user will be substituted appropriately.
- *
- * @param user
- * The user whose credentials should be used if necessary.
+ * The ID of the active connection being joined, as provided by guacd
+ * when the original connection was established, or null if a new
+ * connection should be established instead.
*
* @param sharingProfile
* The sharing profile whose associated parameters dictate the level
- * of access granted to the user joining the connection.
- *
- * @param connectionID
- * The ID of the connection being joined, as provided by guacd when the
- * original connection was established, or null if a new connection
- * should be created instead.
+ * of access granted to the user joining the connection, or null if the
+ * parameters associated with the connection should be used.
*
* @return
- * A GuacamoleConfiguration containing the protocol and parameters from
- * the given connection.
+ * A GuacamoleConfiguration defining the requested, possibly shared
+ * connection.
*/
- private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
- ModeledSharingProfile sharingProfile, String connectionID) {
+ private GuacamoleConfiguration getGuacamoleConfiguration(
+ ModeledConnection connection, String connectionID,
+ ModeledSharingProfile sharingProfile) {
+
+ ConnectionModel model = connection.getModel();
// Generate configuration from available data
GuacamoleConfiguration config = new GuacamoleConfiguration();
+ config.setProtocol(model.getProtocol());
config.setConnectionID(connectionID);
// Set parameters from associated data
- Collection<SharingProfileParameterModel> parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier());
- for (SharingProfileParameterModel parameter : parameters)
- config.setParameter(parameter.getName(), parameter.getValue());
+ if (sharingProfile != null) {
+ Collection<SharingProfileParameterModel> parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier());
+ for (SharingProfileParameterModel parameter : parameters)
+ config.setParameter(parameter.getName(), parameter.getValue());
+ }
+ else {
+ Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
+ for (ConnectionParameterModel parameter : parameters)
+ config.setParameter(parameter.getName(), parameter.getValue());
+ }
return config;
@@ -488,7 +453,7 @@
if (activeConnection.isPrimaryConnection()) {
activeConnections.put(connection.getIdentifier(), activeConnection);
activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection);
- config = getGuacamoleConfiguration(activeConnection.getUser(), connection, activeConnection.getConnectionID());
+ config = getGuacamoleConfiguration(connection, activeConnection.getConnectionID(), null);
}
// If we ARE joining an active connection under the restrictions of
@@ -502,8 +467,7 @@
// Build configuration from the sharing profile and the ID of
// the connection being joined
- config = getGuacamoleConfiguration(activeConnection.getUser(),
- activeConnection.getSharingProfile(), connectionID);
+ config = getGuacamoleConfiguration(connection, connectionID, activeConnection.getSharingProfile());
}
diff --git a/guacamole-common-js/src/main/webapp/modules/Tunnel.js b/guacamole-common-js/src/main/webapp/modules/Tunnel.js
index 149dce4..1464266 100644
--- a/guacamole-common-js/src/main/webapp/modules/Tunnel.js
+++ b/guacamole-common-js/src/main/webapp/modules/Tunnel.js
@@ -74,6 +74,20 @@
};
/**
+ * Changes the stored UUID that uniquely identifies this tunnel, firing the
+ * onuuid event if a handler has been defined.
+ *
+ * @private
+ * @param {String} uuid
+ * The new state of this tunnel.
+ */
+ this.setUUID = function setUUID(uuid) {
+ this.uuid = uuid;
+ if (this.onuuid)
+ this.onuuid(uuid);
+ };
+
+ /**
* Returns whether this tunnel is currently connected.
*
* @returns {Boolean}
@@ -120,6 +134,15 @@
this.uuid = null;
/**
+ * Fired when the UUID that uniquely identifies this tunnel is known.
+ *
+ * @event
+ * @param {String}
+ * The UUID uniquely identifying this tunnel.
+ */
+ this.onuuid = null;
+
+ /**
* Fired whenever an error is encountered by the tunnel.
*
* @event
@@ -706,7 +729,7 @@
reset_timeout();
// Get UUID from response
- tunnel.uuid = connect_xmlhttprequest.responseText;
+ tunnel.setUUID(connect_xmlhttprequest.responseText);
// Mark as open
tunnel.setState(Guacamole.Tunnel.State.OPEN);
@@ -1019,7 +1042,7 @@
// Associate tunnel UUID if received
if (opcode === Guacamole.Tunnel.INTERNAL_DATA_OPCODE)
- tunnel.uuid = elements[0];
+ tunnel.setUUID(elements[0]);
// Tunnel is now open and UUID is available
tunnel.setState(Guacamole.Tunnel.State.OPEN);
@@ -1155,11 +1178,18 @@
* @private
*/
function commit_tunnel() {
+
tunnel.onstatechange = chained_tunnel.onstatechange;
tunnel.oninstruction = chained_tunnel.oninstruction;
tunnel.onerror = chained_tunnel.onerror;
- chained_tunnel.uuid = tunnel.uuid;
+ tunnel.onuuid = chained_tunnel.onuuid;
+
+ // Assign UUID if already known
+ if (tunnel.uuid)
+ chained_tunnel.setUUID(tunnel.uuid);
+
committedTunnel = tunnel;
+
}
// Wrap own onstatechange within current tunnel
diff --git a/guacamole-common/pom.xml b/guacamole-common/pom.xml
index b8e09d4..f9fb82a 100644
--- a/guacamole-common/pom.xml
+++ b/guacamole-common/pom.xml
@@ -57,14 +57,14 @@
<build>
<plugins>
- <!-- Written for 1.6 -->
+ <!-- Written for 1.8 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
- <source>1.6</source>
- <target>1.6</target>
+ <source>1.8</source>
+ <target>1.8</target>
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-Werror</arg>
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/net/DelegatingGuacamoleSocket.java b/guacamole-common/src/main/java/org/apache/guacamole/net/DelegatingGuacamoleSocket.java
new file mode 100644
index 0000000..b519629
--- /dev/null
+++ b/guacamole-common/src/main/java/org/apache/guacamole/net/DelegatingGuacamoleSocket.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.net;
+
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.io.GuacamoleReader;
+import org.apache.guacamole.io.GuacamoleWriter;
+
+/**
+ * GuacamoleSocket implementation which simply delegates all function calls to
+ * an underlying GuacamoleSocket.
+ */
+public class DelegatingGuacamoleSocket implements GuacamoleSocket {
+
+ /**
+ * The wrapped socket.
+ */
+ private final GuacamoleSocket socket;
+
+ /**
+ * Wraps the given GuacamoleSocket such that all function calls against
+ * this DelegatingGuacamoleSocket will be delegated to it.
+ *
+ * @param socket
+ * The GuacamoleSocket to wrap.
+ */
+ public DelegatingGuacamoleSocket(GuacamoleSocket socket) {
+ this.socket = socket;
+ }
+
+ /**
+ * Returns the underlying GuacamoleSocket wrapped by this
+ * DelegatingGuacamoleSocket.
+ *
+ * @return
+ * The GuacamoleSocket wrapped by this DelegatingGuacamoleSocket.
+ */
+ protected GuacamoleSocket getDelegateSocket() {
+ return socket;
+ }
+
+ @Override
+ public String getProtocol() {
+ return socket.getProtocol();
+ }
+
+ @Override
+ public GuacamoleReader getReader() {
+ return socket.getReader();
+ }
+
+ @Override
+ public GuacamoleWriter getWriter() {
+ return socket.getWriter();
+ }
+
+ @Override
+ public void close() throws GuacamoleException {
+ socket.close();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return socket.isOpen();
+ }
+
+}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/net/GuacamoleSocket.java b/guacamole-common/src/main/java/org/apache/guacamole/net/GuacamoleSocket.java
index 4d084e4..af068fa 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/net/GuacamoleSocket.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/net/GuacamoleSocket.java
@@ -30,6 +30,24 @@
public interface GuacamoleSocket {
/**
+ * Returns the name of the protocol to be used. If the protocol is not
+ * known or the implementation refuses to reveal the underlying protocol,
+ * null is returned.
+ *
+ * <p>Implementations <strong>should</strong> aim to expose the name of the
+ * underlying protocol, such that protocol-specific responses like the
+ * "required" and "argv" instructions can be handled correctly by code
+ * consuming the GuacamoleSocket.
+ *
+ * @return
+ * The name of the protocol to be used, or null if this information is
+ * not available.
+ */
+ public default String getProtocol() {
+ return null;
+ }
+
+ /**
* Returns a GuacamoleReader which can be used to read from the
* Guacamole instruction stream associated with the connection
* represented by this GuacamoleSocket.
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/ConfiguredGuacamoleSocket.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/ConfiguredGuacamoleSocket.java
index fe4efca..6cf3d7b 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/ConfiguredGuacamoleSocket.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/ConfiguredGuacamoleSocket.java
@@ -24,6 +24,7 @@
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.io.GuacamoleReader;
import org.apache.guacamole.io.GuacamoleWriter;
+import org.apache.guacamole.net.DelegatingGuacamoleSocket;
import org.apache.guacamole.net.GuacamoleSocket;
/**
@@ -36,12 +37,7 @@
* this GuacamoleSocket from manually controlling the initial protocol
* handshake.
*/
-public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
-
- /**
- * The wrapped socket.
- */
- private GuacamoleSocket socket;
+public class ConfiguredGuacamoleSocket extends DelegatingGuacamoleSocket {
/**
* The configuration to use when performing the Guacamole protocol
@@ -125,7 +121,7 @@
GuacamoleConfiguration config,
GuacamoleClientInformation info) throws GuacamoleException {
- this.socket = socket;
+ super(socket);
this.config = config;
// Get reader and writer
@@ -268,23 +264,8 @@
}
@Override
- public GuacamoleWriter getWriter() {
- return socket.getWriter();
- }
-
- @Override
- public GuacamoleReader getReader() {
- return socket.getReader();
- }
-
- @Override
- public void close() throws GuacamoleException {
- socket.close();
- }
-
- @Override
- public boolean isOpen() {
- return socket.isOpen();
+ public String getProtocol() {
+ return getConfiguration().getProtocol();
}
}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/FailoverGuacamoleSocket.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/FailoverGuacamoleSocket.java
index 3c64c51..15414c0 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/FailoverGuacamoleSocket.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/FailoverGuacamoleSocket.java
@@ -28,7 +28,7 @@
import org.apache.guacamole.GuacamoleUpstreamTimeoutException;
import org.apache.guacamole.GuacamoleUpstreamUnavailableException;
import org.apache.guacamole.io.GuacamoleReader;
-import org.apache.guacamole.io.GuacamoleWriter;
+import org.apache.guacamole.net.DelegatingGuacamoleSocket;
import org.apache.guacamole.net.GuacamoleSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +40,7 @@
* constructor, allowing a different socket to be substituted prior to
* fulfilling the connection.
*/
-public class FailoverGuacamoleSocket implements GuacamoleSocket {
+public class FailoverGuacamoleSocket extends DelegatingGuacamoleSocket {
/**
* Logger for this class.
@@ -55,11 +55,6 @@
private static final int DEFAULT_INSTRUCTION_QUEUE_LIMIT = 131072;
/**
- * The wrapped socket being used.
- */
- private final GuacamoleSocket socket;
-
- /**
* Queue of all instructions read while this FailoverGuacamoleSocket was
* being constructed.
*/
@@ -158,6 +153,8 @@
final int instructionQueueLimit)
throws GuacamoleException, GuacamoleUpstreamException {
+ super(socket);
+
int totalQueueSize = 0;
GuacamoleInstruction instruction;
@@ -189,8 +186,6 @@
}
- this.socket = socket;
-
}
/**
@@ -230,7 +225,7 @@
@Override
public boolean available() throws GuacamoleException {
- return !instructionQueue.isEmpty() || socket.getReader().available();
+ return !instructionQueue.isEmpty() || getDelegateSocket().getReader().available();
}
@Override
@@ -244,7 +239,7 @@
return instruction.toString().toCharArray();
}
- return socket.getReader().read();
+ return getDelegateSocket().getReader().read();
}
@@ -258,7 +253,7 @@
if (!instructionQueue.isEmpty())
return instructionQueue.remove();
- return socket.getReader().readInstruction();
+ return getDelegateSocket().getReader().readInstruction();
}
@@ -269,19 +264,4 @@
return queuedReader;
}
- @Override
- public GuacamoleWriter getWriter() {
- return socket.getWriter();
- }
-
- @Override
- public void close() throws GuacamoleException {
- socket.close();
- }
-
- @Override
- public boolean isOpen() {
- return socket.isOpen();
- }
-
}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/FilteredGuacamoleSocket.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/FilteredGuacamoleSocket.java
index 5e541d0..c3bfefd 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/FilteredGuacamoleSocket.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/FilteredGuacamoleSocket.java
@@ -19,21 +19,16 @@
package org.apache.guacamole.protocol;
-import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.io.GuacamoleReader;
import org.apache.guacamole.io.GuacamoleWriter;
+import org.apache.guacamole.net.DelegatingGuacamoleSocket;
import org.apache.guacamole.net.GuacamoleSocket;
/**
* Implementation of GuacamoleSocket which allows individual instructions to be
* intercepted, overridden, etc.
*/
-public class FilteredGuacamoleSocket implements GuacamoleSocket {
-
- /**
- * Wrapped GuacamoleSocket.
- */
- private final GuacamoleSocket socket;
+public class FilteredGuacamoleSocket extends DelegatingGuacamoleSocket {
/**
* A reader for the wrapped GuacamoleSocket which may be filtered.
@@ -58,7 +53,8 @@
* instructions, if any.
*/
public FilteredGuacamoleSocket(GuacamoleSocket socket, GuacamoleFilter readFilter, GuacamoleFilter writeFilter) {
- this.socket = socket;
+
+ super(socket);
// Apply filter to reader
if (readFilter != null)
@@ -84,14 +80,4 @@
return writer;
}
- @Override
- public void close() throws GuacamoleException {
- socket.close();
- }
-
- @Override
- public boolean isOpen() {
- return socket.isOpen();
- }
-
}
diff --git a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleConfiguration.java b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleConfiguration.java
index 48d7e52..5c96066 100644
--- a/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleConfiguration.java
+++ b/guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleConfiguration.java
@@ -92,8 +92,7 @@
/**
* Sets the ID of the connection being joined, if any. If no connection
- * is being joined, this value must be omitted, and the protocol must be
- * set instead.
+ * is being joined, this value must be omitted.
*
* @param connectionID The ID of the connection being joined.
*/
@@ -103,15 +102,34 @@
/**
* Returns the name of the protocol to be used.
- * @return The name of the protocol to be used.
+ *
+ * @return
+ * The name of the protocol to be used.
*/
public String getProtocol() {
return protocol;
}
/**
- * Sets the name of the protocol to be used.
- * @param protocol The name of the protocol to be used.
+ * Sets the name of the protocol to be used. If no connection is being
+ * joined (a new connection is being established), this value must be set.
+ *
+ * <p>If a connection is being joined, <strong>this value should still be
+ * set</strong> to ensure that protocol-specific responses like the
+ * "required" and "argv" instructions can be understood in their proper
+ * context by other code that may consume this GuacamoleConfiguration like
+ * {@link ConfiguredGuacamoleSocket}.
+ *
+ * <p>If this value is unavailable or remains unset, it is still possible
+ * to join an established connection using
+ * {@link #setConnectionID(java.lang.String)}, however protocol-specific
+ * responses like the "required" and "argv" instructions might not be
+ * possible to handle correctly if the underlying protocol is not made
+ * available through some other means to the client receiving those
+ * responses.
+ *
+ * @param protocol
+ * The name of the protocol to be used.
*/
public void setProtocol(String protocol) {
this.protocol = protocol;
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
index 5397339..74347b7 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/tunnel/TunnelResource.java
@@ -24,6 +24,7 @@
import com.google.inject.assistedinject.AssistedInject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -31,8 +32,10 @@
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleResourceNotFoundException;
+import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.UserContext;
+import org.apache.guacamole.protocols.ProtocolInfo;
import org.apache.guacamole.rest.activeconnection.APIActiveConnection;
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
@@ -58,6 +61,12 @@
private final UserTunnel tunnel;
/**
+ * The Guacamole server environment.
+ */
+ @Inject
+ private Environment environment;
+
+ /**
* A factory which can be used to create instances of resources representing
* ActiveConnections.
*/
@@ -107,6 +116,39 @@
}
/**
+ * Retrieves the underlying protocol used by the connection associated with
+ * this tunnel. If possible, the parameters available for that protocol are
+ * retrieved, as well.
+ *
+ * @return
+ * A ProtocolInfo object describing the protocol used by the connection
+ * associated with this tunnel.
+ *
+ * @throws GuacamoleException
+ * If the protocol used by the connection associated with this tunnel
+ * cannot be determined.
+ */
+ @GET
+ @Path("protocol")
+ public ProtocolInfo getProtocol() throws GuacamoleException {
+
+ // Pull protocol name from underlying socket
+ String protocol = tunnel.getSocket().getProtocol();
+ if (protocol == null)
+ throw new GuacamoleResourceNotFoundException("Protocol of tunnel is not known/exposed.");
+
+ // If there is no such protocol defined, provide as much info as is
+ // known (just the name)
+ ProtocolInfo info = environment.getProtocol(protocol);
+ if (info == null)
+ return new ProtocolInfo(protocol);
+
+ // All protocol information for this tunnel is known
+ return info;
+
+ }
+
+ /**
* Intercepts and returns the entire contents of a specific stream.
*
* @param streamIndex
diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
index b40a949..12b9f57 100644
--- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js
+++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js
@@ -386,7 +386,16 @@
status.code);
});
};
-
+
+ // Pull protocol-specific information from tunnel once tunnel UUID is
+ // known
+ tunnel.onuuid = function tunnelAssignedUUID(uuid) {
+ tunnelService.getProtocol(uuid).then(function protocolRetrieved(protocol) {
+ managedClient.protocol = protocol.name;
+ managedClient.forms = protocol.connectionForms;
+ }, requestService.WARN);
+ };
+
// Update connection state as tunnel state changes
tunnel.onstatechange = function tunnelStateChanged(state) {
$rootScope.$evalAsync(function updateTunnelState() {
@@ -612,14 +621,9 @@
// If using a connection, pull connection name and protocol information
if (clientIdentifier.type === ClientIdentifier.Types.CONNECTION) {
- $q.all({
- connection : connectionService.getConnection(clientIdentifier.dataSource, clientIdentifier.id),
- protocols : schemaService.getProtocols(clientIdentifier.dataSource)
- })
- .then(function dataRetrieved(values) {
- managedClient.name = managedClient.title = values.connection.name;
- managedClient.protocol = values.connection.protocol;
- managedClient.forms = values.protocols[values.connection.protocol].connectionForms;
+ connectionService.getConnection(clientIdentifier.dataSource, clientIdentifier.id)
+ .then(function connectionRetrieved(connection) {
+ managedClient.name = managedClient.title = connection.name;
}, requestService.WARN);
}
@@ -640,14 +644,9 @@
// Attempt to retrieve connection details only if the
// underlying connection is known
if (activeConnection.connectionIdentifier) {
- $q.all({
- connection : connectionService.getConnection(clientIdentifier.dataSource, activeConnection.connectionIdentifier),
- protocols : schemaService.getProtocols(clientIdentifier.dataSource)
- })
- .then(function dataRetrieved(values) {
- managedClient.name = managedClient.title = values.connection.name;
- managedClient.protocol = values.connection.protocol;
- managedClient.forms = values.protocols[values.connection.protocol].connectionForms;
+ connectionService.getConnection(clientIdentifier.dataSource, activeConnection.connectionIdentifier)
+ .then(function connectionRetrieved(connection) {
+ managedClient.name = managedClient.title = connection.name;
}, requestService.WARN);
}
diff --git a/guacamole/src/main/webapp/app/rest/services/tunnelService.js b/guacamole/src/main/webapp/app/rest/services/tunnelService.js
index 1dba527..3cfdb35 100644
--- a/guacamole/src/main/webapp/app/rest/services/tunnelService.js
+++ b/guacamole/src/main/webapp/app/rest/services/tunnelService.js
@@ -80,6 +80,36 @@
};
/**
+ * Makes a request to the REST API to retrieve the underlying protocol of
+ * the connection associated with a particular tunnel, returning a promise
+ * that provides a @link{Protocol} object if successful.
+ *
+ * @param {String} tunnel
+ * The UUID of the tunnel associated with the Guacamole connection
+ * whose underlying protocol is being retrieved.
+ *
+ * @returns {Promise.<Protocol>}
+ * A promise which will resolve with a @link{Protocol} object upon
+ * success.
+ */
+ service.getProtocol = function getProtocol(tunnel) {
+
+ // Build HTTP parameters set
+ var httpParameters = {
+ token : authenticationService.getCurrentToken()
+ };
+
+ // Retrieve the protocol details of the specified tunnel
+ return requestService({
+ method : 'GET',
+ url : 'api/session/tunnels/' + encodeURIComponent(tunnel)
+ + '/protocol',
+ params : httpParameters
+ });
+
+ };
+
+ /**
* Retrieves the set of sharing profiles that the current user can use to
* share the active connection of the given tunnel.
*