diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/AbstractGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/AbstractGuacamoleSocketService.java index 084823684..08da2decc 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/AbstractGuacamoleSocketService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/AbstractGuacamoleSocketService.java @@ -139,6 +139,37 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS protected abstract void release(AuthenticatedUser user, ModeledConnection connection); + /** + * Acquires possibly-exclusive access to the given connection group on + * behalf of the given user. If access is denied for any reason, an + * exception is thrown. + * + * @param user + * The user acquiring access. + * + * @param connectionGroup + * The connection group being accessed. + * + * @throws GuacamoleException + * If access is denied to the given user for any reason. + */ + protected abstract void acquire(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) throws GuacamoleException; + + /** + * Releases possibly-exclusive access to the given connection group on + * behalf of the given user. If the given user did not already have access, + * the behavior of this function is undefined. + * + * @param user + * The user releasing access. + * + * @param connectionGroup + * The connection group being released. + */ + protected abstract void release(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup); + /** * Returns a guacamole configuration containing the protocol and parameters * from the given connection. If tokens are used in the connection @@ -254,6 +285,11 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS * @param user * The user for whom the connection is being established. * + * @param balancingGroup, + * The associated balancing group, if any. If the connection is not + * associated with a balancing group, or the connection is being used + * manually, this will be null. + * * @param connection * The connection the user is connecting to. * @@ -270,6 +306,7 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS * while connection configuration information is being retrieved. */ private GuacamoleSocket connect(final AuthenticatedUser user, + final ModeledConnectionGroup balancingGroup, final ModeledConnection connection, GuacamoleClientInformation info) throws GuacamoleException { @@ -309,6 +346,10 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS activeConnectionGroups.remove(parentIdentifier, activeConnection); release(user, connection); + // Release any associated group + if (balancingGroup != null) + release(user, balancingGroup); + // Save record to database saveConnectionRecord(identifier, activeConnection); @@ -325,9 +366,16 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS // Release connection if not already released if (released.compareAndSet(false, true)) { + + // Release connection activeConnections.remove(identifier, activeConnection); activeConnectionGroups.remove(parentIdentifier, activeConnection); release(user, connection); + + // Release any associated group + if (balancingGroup != null) + release(user, balancingGroup); + } throw e; @@ -344,7 +392,7 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS // Acquire and connect to single connection acquire(user, Collections.singletonList(connection)); - return connect(user, connection, info); + return connect(user, null, connection, info); } @@ -368,7 +416,10 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS if (identifiers.isEmpty()) throw new GuacamoleSecurityException("Permission denied."); - // Otherwise, retrieve all children + // Acquire group + acquire(user, connectionGroup); + + // Retrieve all children Collection models = connectionMapper.select(identifiers); List connections = new ArrayList(models.size()); @@ -381,7 +432,7 @@ public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketS // Acquire and connect to any child ModeledConnection connection = acquire(user, connections); - return connect(user, connection, info); + return connect(user, connectionGroup, connection, info); } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/BalancedGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/BalancedGuacamoleSocketService.java new file mode 100644 index 000000000..118c0cad9 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/BalancedGuacamoleSocketService.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.auth.jdbc.socket; + +import com.google.inject.Singleton; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.GuacamoleResourceConflictException; +import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; + + +/** + * GuacamoleSocketService implementation which allows only one user per + * connection at any time, but does not disallow concurrent use of connection + * groups. If a user attempts to use a connection group multiple times, they + * will receive different underlying connections each time until the group is + * exhausted. + * + * @author Michael Jumper + */ +@Singleton +public class BalancedGuacamoleSocketService + extends AbstractGuacamoleSocketService { + + /** + * The set of all active connection identifiers. + */ + private final Set activeConnections = + Collections.newSetFromMap(new ConcurrentHashMap()); + + @Override + protected ModeledConnection acquire(AuthenticatedUser user, + List connections) throws GuacamoleException { + + // Return the first unused connection + for (ModeledConnection connection : connections) { + if (activeConnections.add(connection.getIdentifier())) + return connection; + } + + // Already in use + throw new GuacamoleResourceConflictException("Cannot connect. This connection is in use."); + + } + + @Override + protected void release(AuthenticatedUser user, ModeledConnection connection) { + activeConnections.remove(connection.getIdentifier()); + } + + @Override + protected void acquire(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) throws GuacamoleException { + // Do nothing + } + + @Override + protected void release(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) { + // Do nothing + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/MultiseatGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/MultiseatGuacamoleSocketService.java index a55e31780..d53408c73 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/MultiseatGuacamoleSocketService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/MultiseatGuacamoleSocketService.java @@ -31,12 +31,13 @@ import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleResourceConflictException; +import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; /** * GuacamoleSocketService implementation which restricts concurrency only on a - * per-user basis. Each connection may be used concurrently any number of - * times, but each concurrent use must be associated with a different user. + * per-user basis. Each connection or group may be used concurrently any number + * of times, but each concurrent use must be associated with a different user. * * @author Michael Jumper */ @@ -44,74 +45,17 @@ import org.glyptodon.guacamole.GuacamoleResourceConflictException; public class MultiseatGuacamoleSocketService extends AbstractGuacamoleSocketService { - /** - * A unique pairing of user and connection. - */ - private static class Seat { - - /** - * The user using this seat. - */ - private final String username; - - /** - * The connection associated with this seat. - */ - private final String connectionIdentifier; - - /** - * Creates a new seat which associated the given user with the given - * connection. - * - * @param username - * The username of the user using this seat. - * - * @param connectionIdentifier - * The identifier of the connection associated with this seat. - */ - public Seat(String username, String connectionIdentifier) { - this.username = username; - this.connectionIdentifier = connectionIdentifier; - } - - @Override - public int hashCode() { - - // The various properties will never be null - assert(username != null); - assert(connectionIdentifier != null); - - // Derive hashcode from username and connection identifier - int hash = 5; - hash = 37 * hash + username.hashCode(); - hash = 37 * hash + connectionIdentifier.hashCode(); - return hash; - - } - - @Override - public boolean equals(Object object) { - - // We are only comparing against other seats here - assert(object instanceof Seat); - Seat seat = (Seat) object; - - // The various properties will never be null - assert(seat.username != null); - assert(seat.connectionIdentifier != null); - - return username.equals(seat.username) - && connectionIdentifier.equals(seat.connectionIdentifier); - - } - - } - /** * The set of all active user/connection pairs. */ private final Set activeSeats = Collections.newSetFromMap(new ConcurrentHashMap()); + + /** + * The set of all active user/connection group pairs. + */ + private final Set activeGroupSeats = + Collections.newSetFromMap(new ConcurrentHashMap()); @Override protected ModeledConnection acquire(AuthenticatedUser user, @@ -135,4 +79,21 @@ public class MultiseatGuacamoleSocketService activeSeats.remove(new Seat(user.getUser().getIdentifier(), connection.getIdentifier())); } + @Override + protected void acquire(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) throws GuacamoleException { + + // Do not allow duplicate use of connection groups + Seat seat = new Seat(user.getUser().getIdentifier(), connectionGroup.getIdentifier()); + if (!activeGroupSeats.add(seat)) + throw new GuacamoleResourceConflictException("Cannot connect. This connection is in use."); + + } + + @Override + protected void release(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) { + activeGroupSeats.remove(new Seat(user.getUser().getIdentifier(), connectionGroup.getIdentifier())); + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/ReservedGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/ReservedGuacamoleSocketService.java deleted file mode 100644 index 8cab0b814..000000000 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/ReservedGuacamoleSocketService.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2015 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package org.glyptodon.guacamole.auth.jdbc.socket; - -import com.google.inject.Singleton; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; -import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; -import org.glyptodon.guacamole.GuacamoleException; -import org.glyptodon.guacamole.GuacamoleResourceConflictException; - - -/** - * GuacamoleSocketService implementation which allows only one user per - * connection at any time, but does not disallow concurrent use. Once - * connected, a user has effectively reserved that connection, and may - * continue to concurrently use that connection any number of times. The - * connection will remain reserved until all associated connections are closed. - * Other users will be denied access to that connection while it is reserved. - * - * @author Michael Jumper - */ -@Singleton -public class ReservedGuacamoleSocketService - extends AbstractGuacamoleSocketService { - - /** - * An arbitrary number of reservations associated with a specific user. - * Initially, each Reservation instance represents exactly one reservation, - * but future calls to acquire() may increase this value. Once the - * reservation count is reduced to zero by calls to release(), a - * Reservation instance is empty and cannot be reused. It must be discarded - * and replaced with a fresh Reservation. - * - * This is necessary as each Reservation will be stored within a Map, and - * the effect of acquire() must be deterministic. If Reservations could be - * reused, the internal count could potentially increase after being - * removed from the map, resulting in a successful acquire() that really - * should have failed. - */ - private static class Reservation { - - /** - * The username of the user associated with this reservation. - */ - private final String username; - - /** - * The number of reservations effectively present under the associated - * username. - */ - private int count = 1; - - /** - * Creates a new reservation which tracks the overall number of - * reservations for a given user. - * @param username - */ - public Reservation(String username) { - this.username = username; - } - - /** - * Attempts to acquire a new reservation under the given username. If - * this reservation is for a different user, or the reservation has - * expired, this will fail. - * - * @param username - * The username of the user to acquire the reservation for. - * - * @return - * true if the reservation was successful, false otherwise. - */ - public boolean acquire(String username) { - - // Acquire always fails if for the wrong user - if (!this.username.equals(username)) - return false; - - // Determine success/failure based on count - synchronized (this) { - - // If already expired, no further reservations are allowed - if (count == 0) - return false; - - // Otherwise, add another reservation, report success - count++; - return true; - - } - - } - - /** - * Releases a previous reservation. The result of calling this function - * without a previous matching call to acquire is undefined. - * - * @return - * true if the last reservation has been released and this - * reservation is now empty, false otherwise. - */ - public boolean release() { - synchronized (this) { - - // Reduce reservation count - count--; - - // Empty if no reservations remain - return count == 0; - - } - } - - } - - /** - * Map of connection identifier to associated reservations. - */ - private final ConcurrentMap reservations = - new ConcurrentHashMap(); - - @Override - protected ModeledConnection acquire(AuthenticatedUser user, - List connections) throws GuacamoleException { - - String username = user.getUser().getIdentifier(); - - // Return the first successfully-reserved connection - for (ModeledConnection connection : connections) { - - String identifier = connection.getIdentifier(); - - // Attempt to reserve connection, return if successful - Reservation reservation = reservations.putIfAbsent(identifier, new Reservation(username)); - if (reservation == null || reservation.acquire(username)) - return connection; - - } - - // Already in use - throw new GuacamoleResourceConflictException("Cannot connect. This connection is in use."); - - } - - @Override - protected void release(AuthenticatedUser user, ModeledConnection connection) { - - String identifier = connection.getIdentifier(); - - // Retrieve active reservation (which must exist) - Reservation reservation = reservations.get(identifier); - assert(reservation != null); - - // Release reservation, remove from map if empty - if (reservation.release()) - reservations.remove(identifier); - - } - -} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/Seat.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/Seat.java new file mode 100644 index 000000000..275536f98 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/Seat.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.auth.jdbc.socket; + +/** + * A unique pairing of user and connection or connection group. + * + * @author Michael Jumper + */ +public class Seat { + + /** + * The user using this seat. + */ + private final String username; + + /** + * The connection or connection group associated with this seat. + */ + private final String identifier; + + /** + * Creates a new seat which associated the given user with the given + * connection or connection group. + * + * @param username + * The username of the user using this seat. + * + * @param identifier + * The identifier of the connection or connection group associated with + * this seat. + */ + public Seat(String username, String identifier) { + this.username = username; + this.identifier = identifier; + } + + @Override + public int hashCode() { + + // The various properties will never be null + assert(username != null); + assert(identifier != null); + + // Derive hashcode from username and connection identifier + int hash = 5; + hash = 37 * hash + username.hashCode(); + hash = 37 * hash + identifier.hashCode(); + return hash; + + } + + @Override + public boolean equals(Object object) { + + // We are only comparing against other seats here + assert(object instanceof Seat); + Seat seat = (Seat) object; + + // The various properties will never be null + assert(seat.username != null); + assert(seat.identifier != null); + + return username.equals(seat.username) + && identifier.equals(seat.identifier); + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/SingleSeatGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/SingleSeatGuacamoleSocketService.java index e3ff6a9a4..b7f092565 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/SingleSeatGuacamoleSocketService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/SingleSeatGuacamoleSocketService.java @@ -31,11 +31,14 @@ import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.GuacamoleResourceConflictException; +import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; /** * GuacamoleSocketService implementation which allows exactly one use - * of any connection at any time. Concurrent usage of any kind is not allowed. + * of any connection at any time. Concurrent usage of connections is not + * allowed, and concurrent usage of connection groups is allowed only between + * different users. * * @author Michael Jumper */ @@ -48,7 +51,13 @@ public class SingleSeatGuacamoleSocketService */ private final Set activeConnections = Collections.newSetFromMap(new ConcurrentHashMap()); - + + /** + * The set of all active user/connection group pairs. + */ + private final Set activeGroupSeats = + Collections.newSetFromMap(new ConcurrentHashMap()); + @Override protected ModeledConnection acquire(AuthenticatedUser user, List connections) throws GuacamoleException { @@ -69,4 +78,21 @@ public class SingleSeatGuacamoleSocketService activeConnections.remove(connection.getIdentifier()); } + @Override + protected void acquire(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) throws GuacamoleException { + + // Do not allow duplicate use of connection groups + Seat seat = new Seat(user.getUser().getIdentifier(), connectionGroup.getIdentifier()); + if (!activeGroupSeats.add(seat)) + throw new GuacamoleResourceConflictException("Cannot connect. This connection is in use."); + + } + + @Override + protected void release(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) { + activeGroupSeats.remove(new Seat(user.getUser().getIdentifier(), connectionGroup.getIdentifier())); + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/UnrestrictedGuacamoleSocketService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/UnrestrictedGuacamoleSocketService.java index c5d2a0503..e5932d8c2 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/UnrestrictedGuacamoleSocketService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/socket/UnrestrictedGuacamoleSocketService.java @@ -27,6 +27,7 @@ import java.util.List; import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection; import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; /** @@ -66,4 +67,16 @@ public class UnrestrictedGuacamoleSocketService // Do nothing } + @Override + protected void acquire(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) throws GuacamoleException { + // Do nothing + } + + @Override + protected void release(AuthenticatedUser user, + ModeledConnectionGroup connectionGroup) { + // Do nothing + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java index c33787a38..3e7463b69 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/java/net/sourceforge/guacamole/net/auth/mysql/MySQLAuthenticationProvider.java @@ -31,7 +31,7 @@ import org.glyptodon.guacamole.net.auth.UserContext; import org.glyptodon.guacamole.auth.jdbc.JDBCAuthenticationProviderModule; import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService; import org.glyptodon.guacamole.auth.jdbc.socket.MultiseatGuacamoleSocketService; -import org.glyptodon.guacamole.auth.jdbc.socket.ReservedGuacamoleSocketService; +import org.glyptodon.guacamole.auth.jdbc.socket.BalancedGuacamoleSocketService; import org.glyptodon.guacamole.auth.jdbc.socket.SingleSeatGuacamoleSocketService; import org.glyptodon.guacamole.auth.jdbc.socket.UnrestrictedGuacamoleSocketService; import org.glyptodon.guacamole.auth.jdbc.user.UserContextService; @@ -85,7 +85,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider { // Connections are reserved for a single user when in use else - return ReservedGuacamoleSocketService.class; + return BalancedGuacamoleSocketService.class; }