mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-1512: Add absolute connection limit properties for MySQL/PostgreSQL.
This commit is contained in:
@@ -44,6 +44,20 @@ public abstract class JDBCEnvironment extends LocalEnvironment {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of concurrent connections to allow overall.
|
||||
* As this limit applies globally (independent of which connection is in
|
||||
* use or which user is using it), this setting cannot be overridden at the
|
||||
* connection level. Zero denotes unlimited.
|
||||
*
|
||||
* @return
|
||||
* The maximum allowable number of concurrent connections.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the property.
|
||||
*/
|
||||
public abstract int getAbsoluteMaxConnections() throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns the default maximum number of concurrent connections to allow to
|
||||
* any one connection, unless specified differently on an individual
|
||||
|
@@ -23,15 +23,18 @@
|
||||
package org.glyptodon.guacamole.auth.jdbc.tunnel;
|
||||
|
||||
import com.google.common.collect.ConcurrentHashMultiset;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.glyptodon.guacamole.GuacamoleClientTooManyException;
|
||||
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.JDBCEnvironment;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
|
||||
|
||||
@@ -47,6 +50,12 @@ import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
public class RestrictedGuacamoleTunnelService
|
||||
extends AbstractGuacamoleTunnelService {
|
||||
|
||||
/**
|
||||
* The environment of the Guacamole server.
|
||||
*/
|
||||
@Inject
|
||||
private JDBCEnvironment environment;
|
||||
|
||||
/**
|
||||
* Set of all currently-active user/connection pairs (seats).
|
||||
*/
|
||||
@@ -67,6 +76,12 @@ public class RestrictedGuacamoleTunnelService
|
||||
*/
|
||||
private final ConcurrentHashMultiset<String> activeGroups = ConcurrentHashMultiset.<String>create();
|
||||
|
||||
/**
|
||||
* The total number of active connections within this instance of
|
||||
* Guacamole.
|
||||
*/
|
||||
private final AtomicInteger totalActiveConnections = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* Attempts to add a single instance of the given value to the given
|
||||
* multiset without exceeding the specified maximum number of values. If
|
||||
@@ -113,10 +128,54 @@ public class RestrictedGuacamoleTunnelService
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to increment the given AtomicInteger without exceeding the
|
||||
* specified maximum value. If the AtomicInteger cannot be incremented
|
||||
* without exceeding the maximum, false is returned.
|
||||
*
|
||||
* @param counter
|
||||
* The AtomicInteger to attempt increment.
|
||||
*
|
||||
* @param max
|
||||
* The maximum value that the given AtomicInteger should contain, or
|
||||
* zero if no limit applies.
|
||||
*
|
||||
* @return
|
||||
* true if the AtomicInteger was successfully incremented without
|
||||
* exceeding the specified maximum, false if the AtomicInteger could
|
||||
* not be incremented.
|
||||
*/
|
||||
private boolean tryIncrement(AtomicInteger counter, int max) {
|
||||
|
||||
// Repeatedly attempt to increment the given AtomicInteger until we
|
||||
// explicitly succeed or explicitly fail
|
||||
while (true) {
|
||||
|
||||
// Get current value
|
||||
int count = counter.get();
|
||||
|
||||
// Bail out if the maximum has already been reached
|
||||
if (count >= max && max != 0)
|
||||
return false;
|
||||
|
||||
// Attempt to increment
|
||||
if (counter.compareAndSet(count, count+1))
|
||||
return true;
|
||||
|
||||
// Try again if unsuccessful
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModeledConnection acquire(AuthenticatedUser user,
|
||||
List<ModeledConnection> connections) throws GuacamoleException {
|
||||
|
||||
// Do not acquire connection unless within overall limits
|
||||
if (!tryIncrement(totalActiveConnections, environment.getAbsoluteMaxConnections()))
|
||||
throw new GuacamoleResourceConflictException("Cannot connect. Overall maximum connections reached.");
|
||||
|
||||
// Get username
|
||||
String username = user.getUser().getIdentifier();
|
||||
|
||||
@@ -160,6 +219,9 @@ public class RestrictedGuacamoleTunnelService
|
||||
|
||||
}
|
||||
|
||||
// Acquire failed
|
||||
totalActiveConnections.decrementAndGet();
|
||||
|
||||
// Too many connections by this user
|
||||
if (userSpecificFailure)
|
||||
throw new GuacamoleClientTooManyException("Cannot connect. Connection already in use by this user.");
|
||||
@@ -174,6 +236,7 @@ public class RestrictedGuacamoleTunnelService
|
||||
protected void release(AuthenticatedUser user, ModeledConnection connection) {
|
||||
activeSeats.remove(new Seat(user.getUser().getIdentifier(), connection.getIdentifier()));
|
||||
activeConnections.remove(connection.getIdentifier());
|
||||
totalActiveConnections.decrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user