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 6687eb36dd..44b65bff59 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 @@ protected abstract void release(RemoteAuthenticatedUser user, 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 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 parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier()); - for (SharingProfileParameterModel parameter : parameters) - config.setParameter(parameter.getName(), parameter.getValue()); + if (sharingProfile != null) { + Collection parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier()); + for (SharingProfileParameterModel parameter : parameters) + config.setParameter(parameter.getName(), parameter.getValue()); + } + else { + Collection parameters = connectionParameterMapper.select(connection.getIdentifier()); + for (ConnectionParameterModel parameter : parameters) + config.setParameter(parameter.getName(), parameter.getValue()); + } return config; @@ -488,7 +453,7 @@ private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConne 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 @@ private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConne // 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 149dce464f..14642667b2 100644 --- a/guacamole-common-js/src/main/webapp/modules/Tunnel.js +++ b/guacamole-common-js/src/main/webapp/modules/Tunnel.js @@ -73,6 +73,20 @@ Guacamole.Tunnel = function() { }; + /** + * 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. * @@ -119,6 +133,15 @@ Guacamole.Tunnel = function() { */ 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. * @@ -706,7 +729,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain, extraTunnelHeaders) { 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 @@ Guacamole.WebSocketTunnel = function(tunnelURL) { // 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 @@ Guacamole.ChainedTunnel = function(tunnelChain) { * @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 b8e09d4742..f9fb82afba 100644 --- a/guacamole-common/pom.xml +++ b/guacamole-common/pom.xml @@ -57,14 +57,14 @@ - + org.apache.maven.plugins maven-compiler-plugin 3.3 - 1.6 - 1.6 + 1.8 + 1.8 -Xlint:all -Werror 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 0000000000..b519629dd7 --- /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 4d084e465f..af068faeaa 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 @@ -29,6 +29,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. + * + *

Implementations should 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 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 fe4efca367..6cf3d7b3cb 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 @@ public ConfiguredGuacamoleSocket(GuacamoleSocket socket, GuacamoleConfiguration config, GuacamoleClientInformation info) throws GuacamoleException { - this.socket = socket; + super(socket); this.config = config; // Get reader and writer @@ -268,23 +264,8 @@ public GuacamoleProtocolVersion getProtocolVersion() { } @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 3c64c51e71..15414c0f54 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. @@ -54,11 +54,6 @@ public class FailoverGuacamoleSocket implements GuacamoleSocket { */ 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 @@ public FailoverGuacamoleSocket(GuacamoleSocket socket, final int instructionQueueLimit) throws GuacamoleException, GuacamoleUpstreamException { + super(socket); + int totalQueueSize = 0; GuacamoleInstruction instruction; @@ -189,8 +186,6 @@ public FailoverGuacamoleSocket(GuacamoleSocket socket, } - this.socket = socket; - } /** @@ -230,7 +225,7 @@ public FailoverGuacamoleSocket(GuacamoleSocket socket) @Override public boolean available() throws GuacamoleException { - return !instructionQueue.isEmpty() || socket.getReader().available(); + return !instructionQueue.isEmpty() || getDelegateSocket().getReader().available(); } @Override @@ -244,7 +239,7 @@ public char[] read() throws GuacamoleException { return instruction.toString().toCharArray(); } - return socket.getReader().read(); + return getDelegateSocket().getReader().read(); } @@ -258,7 +253,7 @@ public GuacamoleInstruction readInstruction() if (!instructionQueue.isEmpty()) return instructionQueue.remove(); - return socket.getReader().readInstruction(); + return getDelegateSocket().getReader().readInstruction(); } @@ -269,19 +264,4 @@ public GuacamoleReader getReader() { 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 5e541d0e38..c3bfefd2ba 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 @@ public class FilteredGuacamoleSocket implements GuacamoleSocket { * 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 @@ public GuacamoleWriter getWriter() { 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 48d7e523ca..5c960661a4 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 @@ public String getConnectionID() { /** * 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 @@ public void setConnectionID(String connectionID) { /** * 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. + * + *

If a connection is being joined, this value should still be + * set 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}. + * + *

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 53973394a2..74347b721f 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; @@ -57,6 +60,12 @@ public class TunnelResource { */ 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. @@ -106,6 +115,39 @@ public TunnelResource(@Assisted UserTunnel tunnel) { } + /** + * 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. * diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js index b40a949947..12b9f5736e 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 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', 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 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', // 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 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', // 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 1dba527a0d..3cfdb35e1e 100644 --- a/guacamole/src/main/webapp/app/rest/services/tunnelService.js +++ b/guacamole/src/main/webapp/app/rest/services/tunnelService.js @@ -79,6 +79,36 @@ angular.module('rest').factory('tunnelService', ['$injector', }; + /** + * 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.} + * 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.