mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 05:31:22 +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();
|
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
|
* Returns the default maximum number of concurrent connections to allow to
|
||||||
* any one connection, unless specified differently on an individual
|
* any one connection, unless specified differently on an individual
|
||||||
|
@@ -23,15 +23,18 @@
|
|||||||
package org.glyptodon.guacamole.auth.jdbc.tunnel;
|
package org.glyptodon.guacamole.auth.jdbc.tunnel;
|
||||||
|
|
||||||
import com.google.common.collect.ConcurrentHashMultiset;
|
import com.google.common.collect.ConcurrentHashMultiset;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientTooManyException;
|
import org.glyptodon.guacamole.GuacamoleClientTooManyException;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.GuacamoleResourceConflictException;
|
import org.glyptodon.guacamole.GuacamoleResourceConflictException;
|
||||||
|
import org.glyptodon.guacamole.auth.jdbc.JDBCEnvironment;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||||
|
|
||||||
|
|
||||||
@@ -47,6 +50,12 @@ import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
|||||||
public class RestrictedGuacamoleTunnelService
|
public class RestrictedGuacamoleTunnelService
|
||||||
extends AbstractGuacamoleTunnelService {
|
extends AbstractGuacamoleTunnelService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The environment of the Guacamole server.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private JDBCEnvironment environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of all currently-active user/connection pairs (seats).
|
* Set of all currently-active user/connection pairs (seats).
|
||||||
*/
|
*/
|
||||||
@@ -67,6 +76,12 @@ public class RestrictedGuacamoleTunnelService
|
|||||||
*/
|
*/
|
||||||
private final ConcurrentHashMultiset<String> activeGroups = ConcurrentHashMultiset.<String>create();
|
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
|
* Attempts to add a single instance of the given value to the given
|
||||||
* multiset without exceeding the specified maximum number of values. If
|
* 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
|
@Override
|
||||||
protected ModeledConnection acquire(AuthenticatedUser user,
|
protected ModeledConnection acquire(AuthenticatedUser user,
|
||||||
List<ModeledConnection> connections) throws GuacamoleException {
|
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
|
// Get username
|
||||||
String username = user.getUser().getIdentifier();
|
String username = user.getUser().getIdentifier();
|
||||||
|
|
||||||
@@ -160,6 +219,9 @@ public class RestrictedGuacamoleTunnelService
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquire failed
|
||||||
|
totalActiveConnections.decrementAndGet();
|
||||||
|
|
||||||
// Too many connections by this user
|
// Too many connections by this user
|
||||||
if (userSpecificFailure)
|
if (userSpecificFailure)
|
||||||
throw new GuacamoleClientTooManyException("Cannot connect. Connection already in use by this user.");
|
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) {
|
protected void release(AuthenticatedUser user, ModeledConnection connection) {
|
||||||
activeSeats.remove(new Seat(user.getUser().getIdentifier(), connection.getIdentifier()));
|
activeSeats.remove(new Seat(user.getUser().getIdentifier(), connection.getIdentifier()));
|
||||||
activeConnections.remove(connection.getIdentifier());
|
activeConnections.remove(connection.getIdentifier());
|
||||||
|
totalActiveConnections.decrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -51,6 +51,12 @@ public class MySQLEnvironment extends JDBCEnvironment {
|
|||||||
*/
|
*/
|
||||||
private static final int DEFAULT_PORT = 3306;
|
private static final int DEFAULT_PORT = 3306;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value for the maximum number of connections to be
|
||||||
|
* allowed to the Guacamole server overall.
|
||||||
|
*/
|
||||||
|
private final int ABSOLUTE_MAX_CONNECTIONS = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value for the default maximum number of connections to be
|
* The default value for the default maximum number of connections to be
|
||||||
* allowed per user to any one connection. Note that, as long as the
|
* allowed per user to any one connection. Note that, as long as the
|
||||||
@@ -164,6 +170,13 @@ public class MySQLEnvironment extends JDBCEnvironment {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAbsoluteMaxConnections() throws GuacamoleException {
|
||||||
|
return getProperty(MySQLGuacamoleProperties.MYSQL_ABSOLUTE_MAX_CONNECTIONS,
|
||||||
|
ABSOLUTE_MAX_CONNECTIONS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultMaxConnections() throws GuacamoleException {
|
public int getDefaultMaxConnections() throws GuacamoleException {
|
||||||
return getProperty(
|
return getProperty(
|
||||||
|
@@ -115,6 +115,19 @@ public class MySQLGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of concurrent connections to allow overall. Zero
|
||||||
|
* denotes unlimited.
|
||||||
|
*/
|
||||||
|
public static final IntegerGuacamoleProperty
|
||||||
|
MYSQL_ABSOLUTE_MAX_CONNECTIONS =
|
||||||
|
new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "mysql-absolute-max-connections"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of concurrent connections to allow to any one
|
* The maximum number of concurrent connections to allow to any one
|
||||||
* connection. Zero denotes unlimited.
|
* connection. Zero denotes unlimited.
|
||||||
|
@@ -50,6 +50,12 @@ public class PostgreSQLEnvironment extends JDBCEnvironment {
|
|||||||
*/
|
*/
|
||||||
private static final int DEFAULT_PORT = 5432;
|
private static final int DEFAULT_PORT = 5432;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default value for the maximum number of connections to be
|
||||||
|
* allowed to the Guacamole server overall.
|
||||||
|
*/
|
||||||
|
private final int ABSOLUTE_MAX_CONNECTIONS = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value for the default maximum number of connections to be
|
* The default value for the default maximum number of connections to be
|
||||||
* allowed per user to any one connection. Note that, as long as the
|
* allowed per user to any one connection. Note that, as long as the
|
||||||
@@ -163,6 +169,13 @@ public class PostgreSQLEnvironment extends JDBCEnvironment {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAbsoluteMaxConnections() throws GuacamoleException {
|
||||||
|
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_ABSOLUTE_MAX_CONNECTIONS,
|
||||||
|
ABSOLUTE_MAX_CONNECTIONS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultMaxConnections() throws GuacamoleException {
|
public int getDefaultMaxConnections() throws GuacamoleException {
|
||||||
return getProperty(
|
return getProperty(
|
||||||
|
@@ -124,6 +124,19 @@ public class PostgreSQLGuacamoleProperties {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of concurrent connections to allow overall. Zero
|
||||||
|
* denotes unlimited.
|
||||||
|
*/
|
||||||
|
public static final IntegerGuacamoleProperty
|
||||||
|
POSTGRESQL_ABSOLUTE_MAX_CONNECTIONS =
|
||||||
|
new IntegerGuacamoleProperty() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() { return "postgresql-absolute-max-connections"; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of concurrent connections to allow to any one
|
* The maximum number of concurrent connections to allow to any one
|
||||||
* connection. Zero denotes unlimited.
|
* connection. Zero denotes unlimited.
|
||||||
|
Reference in New Issue
Block a user