From 79680219cffb37e69c4524ae345d577991c77a99 Mon Sep 17 00:00:00 2001 From: Vasily Loginov Date: Fri, 13 Feb 2015 16:32:36 +0600 Subject: [PATCH 1/5] GUAC-1086: Split TunnelRequestService.createTunnel method into three methods solving separate tasks. --- .../net/basic/TunnelRequestService.java | 106 +++++++++++++----- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index 25e7c87fe..63665a29b 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -148,33 +148,13 @@ public class TunnelRequestService { } - /** - * Creates a new tunnel using the parameters and credentials present in - * the given request. - * - * @param request The request describing the tunnel to create. - * @return The created tunnel, or null if the tunnel could not be created. - * @throws GuacamoleException If an error occurs while creating the tunnel. + * Reads and returns client information provided by the {@code request} parameter. + * + * @param request The request describing tunnel to create. + * @return GuacamoleClientInformation Object containing information about the client sending the tunnel request. */ - public GuacamoleTunnel createTunnel(TunnelRequest request) - throws GuacamoleException { - - // Get auth token and session - final String authToken = request.getParameter("authToken"); - GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - - // Get ID of connection - String id = request.getParameter("id"); - TunnelRequest.IdentifierType id_type = TunnelRequest.IdentifierType.getType(id); - - // Do not continue if unable to determine type - if (id_type == null) - throw new GuacamoleClientException("Illegal identifier - unknown type."); - - // Remove prefix - id = id.substring(id_type.PREFIX.length()); - + protected GuacamoleClientInformation getClientInformation(TunnelRequest request) { // Get client information GuacamoleClientInformation info = new GuacamoleClientInformation(); @@ -203,6 +183,32 @@ public class TunnelRequestService { if (video_mimetypes != null) info.getVideoMimetypes().addAll(video_mimetypes); + return info; + } + + /** + * Creates a new socket using client information specified in the {@code info} parameter, + * connection information from {@code request} and credentials from the {@code session} parameter. + * + * @param request The request describing tunnel to create. + * @param session Current guacamole session. + * @param info Guacamole client information. + * @return Socket connected using the provided settings. + * @throws GuacamoleException If an error occurs while creating the socket. + */ + protected GuacamoleSocket createConnectedSocket(TunnelRequest request, GuacamoleSession session, + GuacamoleClientInformation info) throws GuacamoleException { + // Get ID of connection + String id = request.getParameter("id"); + TunnelRequest.IdentifierType id_type = TunnelRequest.IdentifierType.getType(id); + + // Do not continue if unable to determine type + if (id_type == null) + throw new GuacamoleClientException("Illegal identifier - unknown type."); + + // Remove prefix + id = id.substring(id_type.PREFIX.length()); + // Create connected socket from identifier GuacamoleSocket socket; switch (id_type) { @@ -214,7 +220,7 @@ public class TunnelRequestService { // Get connection directory Directory directory = - context.getRootConnectionGroup().getConnectionDirectory(); + context.getRootConnectionGroup().getConnectionDirectory(); // Get authorized connection Connection connection = directory.get(id); @@ -236,7 +242,7 @@ public class TunnelRequestService { // Get connection group directory Directory directory = - context.getRootConnectionGroup().getConnectionGroupDirectory(); + context.getRootConnectionGroup().getConnectionGroupDirectory(); // Get authorized connection group ConnectionGroup group = directory.get(id); @@ -256,9 +262,21 @@ public class TunnelRequestService { throw new GuacamoleClientException("Connection not supported for provided identifier type."); } + return socket; + } - // Associate socket with tunnel - GuacamoleTunnel tunnel = new GuacamoleTunnel(socket) { + + /** + * Creates and returns a tunnel using the specified guacd socket. + * The tunnel is associated with a session identified + * by the {@code authToken} parameter. + * + * @param socket The connected socket. + * @param authToken Current authorization token. + * @return The created tunnel. + */ + protected GuacamoleTunnel createAssociatedTunnel(GuacamoleSocket socket, final String authToken) { + return new GuacamoleTunnel(socket) { @Override public GuacamoleReader acquireReader() { @@ -281,7 +299,7 @@ public class TunnelRequestService { // Pass through by default. return super.acquireReader(); - + } @Override @@ -303,13 +321,39 @@ public class TunnelRequestService { throw new GuacamoleException("Tunnel close canceled by listener."); session.removeTunnel(getUUID().toString()); - + // Close if no exception due to listener super.close(); } }; + } + + + /** + * Creates a new tunnel using the parameters and credentials present in + * the given request. + * + * @param request The request describing the tunnel to create. + * @return The created tunnel, or null if the tunnel could not be created. + * @throws GuacamoleException If an error occurs while creating the tunnel. + */ + public GuacamoleTunnel createTunnel(TunnelRequest request) + throws GuacamoleException { + + // Get auth token and session + final String authToken = request.getParameter("authToken"); + final GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); + + // Get client information + final GuacamoleClientInformation info = getClientInformation(request); + + // Create connected socket from identifier + final GuacamoleSocket socket = createConnectedSocket(request, session, info); + + // Associate socket with tunnel + GuacamoleTunnel tunnel = createAssociatedTunnel(socket, authToken); // Notify listeners about connection if (!notifyConnect(session, tunnel)) { From f0c20a4fd7c02c418e7dca90546d77c544d7fe9b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Mar 2015 13:26:50 -0700 Subject: [PATCH 2/5] GUAC-1086: Update comments to match current style and recent changes to the API. --- .../net/basic/TunnelRequestService.java | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index 08142624f..9b275f508 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -187,14 +187,24 @@ public class TunnelRequestService { } /** - * Creates a new socket using client information specified in the {@code info} parameter, - * connection information from {@code request} and credentials from the {@code session} parameter. + * Creates a new tunnel using client information specified in the + * {@code info} parameter, connection information from {@code request} and + * credentials from the {@code session} parameter. * - * @param request The request describing tunnel to create. - * @param session Current guacamole session. - * @param info Guacamole client information. - * @return Socket connected using the provided settings. - * @throws GuacamoleException If an error occurs while creating the socket. + * @param request + * The request describing tunnel to create. + * + * @param session + * The Guacamole session for which the tunnel is being created. + * + * @param info + * Information describing the connected Guacamole client. + * + * @return + * A new tunnel, connected as required by the request. + * + * @throws GuacamoleException + * If an error occurs while creating the tunnel. */ protected GuacamoleTunnel createConnectedTunnel(TunnelRequest request, GuacamoleSession session, GuacamoleClientInformation info) throws GuacamoleException { @@ -209,7 +219,7 @@ public class TunnelRequestService { // Remove prefix id = id.substring(id_type.PREFIX.length()); - // Create connected socket from identifier + // Create connected tunnel from identifier GuacamoleTunnel tunnel; switch (id_type) { @@ -264,17 +274,23 @@ public class TunnelRequestService { } /** - * Creates and returns a tunnel using the specified guacd socket. - * The tunnel is associated with a session identified - * by the {@code authToken} parameter. + * Creates and returns a tunnel which wraps the given tunnel, monitoring it + * for closure and, if enabled, clipboard changes. The tunnel is associated + * with a session identified by the {@code authToken} parameter. * - * @param tunnel The connected tunnel. - * @param authToken Current authorization token. - * @return The created tunnel. + * @param tunnel + * The connected tunnel to wrap and monitor. + * + * @param authToken + * The authorization token associated with the session for which this + * tunnel is being created. + * + * @return + * A new tunnel which monitors the given tunnel. */ protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel, final String authToken) { - // Associate socket with tunnel + // Monitor tunnel closure and data return new DelegatingGuacamoleTunnel(tunnel) { @Override @@ -334,10 +350,15 @@ public class TunnelRequestService { /** * Creates a new tunnel using the parameters and credentials present in * the given request. - * - * @param request The request describing the tunnel to create. - * @return The created tunnel, or null if the tunnel could not be created. - * @throws GuacamoleException If an error occurs while creating the tunnel. + * + * @param request + * The request describing the tunnel to create. + * + * @return + * The created tunnel, or null if the tunnel could not be created. + * + * @throws GuacamoleException + * If an error occurs while creating the tunnel. */ public GuacamoleTunnel createTunnel(TunnelRequest request) throws GuacamoleException { From 180fe738a7eefa34ef97120cf8f3b1286b6622f8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Mar 2015 14:04:54 -0700 Subject: [PATCH 3/5] GUAC-1086: Modify semantics of tunnel creation functions to be more sane with respect to recent API changes. --- .../net/basic/TunnelRequestService.java | 98 +++++++++---------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index 9b275f508..0a681259a 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -29,7 +29,6 @@ import java.util.List; import org.glyptodon.guacamole.GuacamoleClientException; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleSecurityException; -import org.glyptodon.guacamole.GuacamoleUnauthorizedException; import org.glyptodon.guacamole.io.GuacamoleReader; import org.glyptodon.guacamole.net.DelegatingGuacamoleTunnel; import org.glyptodon.guacamole.net.GuacamoleTunnel; @@ -187,15 +186,20 @@ public class TunnelRequestService { } /** - * Creates a new tunnel using client information specified in the - * {@code info} parameter, connection information from {@code request} and - * credentials from the {@code session} parameter. + * Creates a new tunnel using which is connected to the connection or + * connection group identifier by the given ID. Client information + * is specified in the {@code info} parameter. * - * @param request - * The request describing tunnel to create. + * @param context + * The UserContext associated with the user for whom the tunnel is + * being created. * - * @param session - * The Guacamole session for which the tunnel is being created. + * @param id + * The ID of the connection or connection group being connected to. For + * connections, this will be of the form "c/IDENTIFIER", where + * IDENTIFIER is the connection identifier. For connection groups, this + * will be of the form "g/IDENTIFIER", where IDENTIFIER is the + * connection group identifier. * * @param info * Information describing the connected Guacamole client. @@ -206,13 +210,11 @@ public class TunnelRequestService { * @throws GuacamoleException * If an error occurs while creating the tunnel. */ - protected GuacamoleTunnel createConnectedTunnel(TunnelRequest request, GuacamoleSession session, + protected GuacamoleTunnel createConnectedTunnel(UserContext context, String id, GuacamoleClientInformation info) throws GuacamoleException { - // Get ID of connection - String id = request.getParameter("id"); - TunnelRequest.IdentifierType id_type = TunnelRequest.IdentifierType.getType(id); - // Do not continue if unable to determine type + // Determine ID type + TunnelRequest.IdentifierType id_type = TunnelRequest.IdentifierType.getType(id); if (id_type == null) throw new GuacamoleClientException("Illegal identifier - unknown type."); @@ -227,7 +229,6 @@ public class TunnelRequestService { case CONNECTION: { // Get connection directory - UserContext context = session.getUserContext(); Directory directory = context.getConnectionDirectory(); // Get authorized connection @@ -247,7 +248,6 @@ public class TunnelRequestService { case CONNECTION_GROUP: { // Get connection group directory - UserContext context = session.getUserContext(); Directory directory = context.getConnectionGroupDirectory(); // Get authorized connection group @@ -274,24 +274,29 @@ public class TunnelRequestService { } /** - * Creates and returns a tunnel which wraps the given tunnel, monitoring it - * for closure and, if enabled, clipboard changes. The tunnel is associated - * with a session identified by the {@code authToken} parameter. + * Associates the given tunnel with the given session, returning a wrapped + * version of the same tunnel which automatically handles closure and + * removal from the session. * * @param tunnel * The connected tunnel to wrap and monitor. * - * @param authToken - * The authorization token associated with the session for which this - * tunnel is being created. + * @param session + * The Guacamole session to associate the tunnel with. * * @return - * A new tunnel which monitors the given tunnel. + * A new tunnel, associated with the given session, which delegates all + * functionality to the given tunnel while monitoring and automatically + * handling closure. + * + * @throws GuacamoleException + * If an error occurs while obtaining the tunnel. */ - protected GuacamoleTunnel createAssociatedTunnel(GuacamoleTunnel tunnel, final String authToken) { + protected GuacamoleTunnel createAssociatedTunnel(final GuacamoleSession session, + GuacamoleTunnel tunnel) throws GuacamoleException { // Monitor tunnel closure and data - return new DelegatingGuacamoleTunnel(tunnel) { + GuacamoleTunnel monitoredTunnel = new DelegatingGuacamoleTunnel(tunnel) { @Override public GuacamoleReader acquireReader() { @@ -300,9 +305,7 @@ public class TunnelRequestService { try { if (GuacamoleProperties.getProperty(ClipboardRESTService.INTEGRATION_ENABLED, false)) { - GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); ClipboardState clipboard = session.getClipboardState(); - return new MonitoringGuacamoleReader(clipboard, super.acquireReader()); } @@ -320,18 +323,7 @@ public class TunnelRequestService { @Override public void close() throws GuacamoleException { - // Get session - just close if session does not exist - GuacamoleSession session; - try { - session = authenticationService.getGuacamoleSession(authToken); - } - catch (GuacamoleUnauthorizedException e) { - logger.debug("Session destroyed prior to tunnel closure.", e); - super.close(); - return; - } - - // If we have a session, signal listeners + // Signal listeners if (!notifyClose(session, this)) throw new GuacamoleException("Tunnel close canceled by listener."); @@ -344,9 +336,18 @@ public class TunnelRequestService { }; + // Notify listeners about connection + if (!notifyConnect(session, monitoredTunnel)) { + logger.info("Successful connection canceled by hook."); + return null; + } + + // Associate tunnel with session + session.addTunnel(monitoredTunnel); + return monitoredTunnel; + } - /** * Creates a new tunnel using the parameters and credentials present in * the given request. @@ -367,25 +368,16 @@ public class TunnelRequestService { final String authToken = request.getParameter("authToken"); final GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - // Get client information + // Get client information and connection ID from request + final String id = request.getParameter("id"); final GuacamoleClientInformation info = getClientInformation(request); - // Create connected tunnel from request - final GuacamoleTunnel tunnel = createConnectedTunnel(request, session, info); + // Create connected tunnel using provided connection ID and client information + final GuacamoleTunnel tunnel = createConnectedTunnel(session.getUserContext(), id, info); // Associate tunnel with session - final GuacamoleTunnel monitoredTunnel = createAssociatedTunnel(tunnel, authToken); - - // Notify listeners about connection - if (!notifyConnect(session, monitoredTunnel)) { - logger.info("Successful connection canceled by hook."); - return null; - } - - session.addTunnel(monitoredTunnel); - return monitoredTunnel; + return createAssociatedTunnel(session, tunnel); } } - From 52e46ea8d0b6cc150f8aab410a4d3ba4e630d4d0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Mar 2015 14:06:22 -0700 Subject: [PATCH 4/5] GUAC-1086: Bring style of getClientInformation() comment up-to-date. --- .../guacamole/net/basic/TunnelRequestService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index 0a681259a..dc0af2509 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -148,10 +148,15 @@ public class TunnelRequestService { } /** - * Reads and returns client information provided by the {@code request} parameter. + * Reads and returns the client information provided within the given + * request. * - * @param request The request describing tunnel to create. - * @return GuacamoleClientInformation Object containing information about the client sending the tunnel request. + * @param request + * The request describing tunnel to create. + * + * @return GuacamoleClientInformation + * An object containing information about the client sending the tunnel + * request. */ protected GuacamoleClientInformation getClientInformation(TunnelRequest request) { // Get client information From d11e83df9617c7f4448a1dea7f94cbca78339fec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 31 Mar 2015 14:07:57 -0700 Subject: [PATCH 5/5] GUAC-1086: Add Vasily Loginov as author. --- .../org/glyptodon/guacamole/net/basic/TunnelRequestService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java index dc0af2509..43ec2d395 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/TunnelRequestService.java @@ -54,6 +54,7 @@ import org.slf4j.LoggerFactory; * that use purely the Guacamole API. * * @author Michael Jumper + * @author Vasily Loginov */ @Singleton public class TunnelRequestService {