From 90f06cbe0b2ff3b1a9d85d2f73fe5864e692341b Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Thu, 7 May 2020 19:30:48 +0200 Subject: Add location selection --- .../de/bwlehrpool/bwlp_guac/ConnectionManager.java | 116 ++++++++++++++++++--- 1 file changed, 99 insertions(+), 17 deletions(-) (limited to 'src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java') diff --git a/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java b/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java index f1ad057..eacb347 100644 --- a/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java +++ b/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java @@ -10,8 +10,7 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.Iterator; -import java.util.LinkedHashMap; +import java.util.*; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -21,6 +20,10 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import org.apache.guacamole.form.Field; +import org.apache.guacamole.net.auth.credentials.CredentialsInfo; +import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; +import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; import org.codehaus.jackson.map.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +34,7 @@ import org.slf4j.LoggerFactory; */ public class ConnectionManager { + private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class); // TODO: Config @@ -38,11 +42,16 @@ public class ConnectionManager { private static final LinkedHashMap clientPool = new LinkedHashMap(); + private static final LinkedHashMap locationPool = new LinkedHashMap(); + + public static LinkedHashMap getLocationPool() { return locationPool; } + /** * Pass plain user name, get existing connection (if any), or a fresh one * @param user (LDAP) user name */ - public static WrappedConnection getForUser(String user) { + public static WrappedConnection getForUser(String user, int locationid) + throws GuacamoleCredentialsException { if (SOURCE_URL == null) { LOGGER.warn("Don't have a source URL for client machines!"); return null; @@ -51,17 +60,35 @@ public class ConnectionManager { updateList(); // Find existing/free client AvailableClient freeClient; - for (;;) { + for (; ; ) { freeClient = null; synchronized (clientPool) { - for (AvailableClient ac : clientPool.values()) { + Collection clients; + if (locationid == 0) { + clients = new HashSet(); + for (JsonLocation loc : locationPool.values()) { + if (!loc.hasPassword()) clients.addAll(loc.clientList); + } + } else { + JsonLocation location = locationPool.get(locationid); + if (location == null) { + // Request the user to select a location + throw new GuacamoleInsufficientCredentialsException( + "Select Location", new CredentialsInfo( + Collections.singletonList(new LocationField()) + )); + } + clients = location.clientList; + } + + for (AvailableClient ac : clients) { if (ac.isInUseBy(user)) { freeClient = ac; break; } } if (freeClient == null) { - for (AvailableClient ac : clientPool.values()) { + for (AvailableClient ac : clients) { if (ac.claim(user)) { freeClient = ac; break; @@ -69,8 +96,13 @@ public class ConnectionManager { } } } - if (freeClient == null) - return null; // TODO: No more clients available -- how to handle? + if (freeClient == null) { + // Request the user to select another location + throw new GuacamoleCredentialsException( + "No free client. Select another location.", new CredentialsInfo( + Collections.singletonList(new LocationField()) + )); + } // Found free or existing client, check if connection is (still) possible if (freeClient.checkConnection(0)) { LOGGER.info("Establishing mapping for user " + user + " to " + freeClient); @@ -79,6 +111,8 @@ public class ConnectionManager { // Connection check failed - release and loop again freeClient.releaseConnection(user); } + } catch (GuacamoleCredentialsException e) { + throw e; } catch (Exception e) { LOGGER.warn("KACKE AM DAMPFEN", e); return null; @@ -91,7 +125,7 @@ public class ConnectionManager { * Fetch fresh client list from satellite server. * Cache for 15 seconds. */ - private static synchronized void updateList() { + public static synchronized void updateList() { long now = System.currentTimeMillis(); if (now < lastUpdate) { lastUpdate = now; @@ -139,23 +173,68 @@ public class ConnectionManager { LOGGER.warn("Not updating local list"); return; } - list = root.clients; - if (list == null) { - LOGGER.info("Client list null"); + + + if (root.locations == null) { + LOGGER.info("Location list null"); } - if (root.locations != null) { - for (JsonLocation l : root.locations) { - LOGGER.info("Location " + l.name + " with pw " + l.password); + synchronized (locationPool) { + for (JsonLocation lnew : root.locations) { + JsonLocation existing = locationPool.get(lnew.id); + boolean redoClientMapping = false; + if (existing == null) { + locationPool.put(lnew.id, lnew); + existing = lnew; + redoClientMapping = true; + } else { + if (existing.locationids != lnew.locationids) redoClientMapping = true; + existing.locationids = lnew.locationids; + existing.name = lnew.name; + existing.password = lnew.password; + } + if (redoClientMapping) { + existing.clientList = new ArrayList(); + for (AvailableClient client : clientPool.values()) { + int locationid = client.getLocationid(); + for (int id : existing.locationids) { + if (id == locationid) { + existing.clientList.add(client); + break; + } + } + } + } + existing.checked = true; + LOGGER.info("Location " + lnew.name + " with pw " + lnew.password); } + for (JsonLocation loc : locationPool.values()) { + if (loc.checked) loc.checked = false; + else locationPool.remove(loc.id); + } + } + + if (root.clients == null) { + LOGGER.info("Client list null"); } synchronized (clientPool) { - for (JsonClient cnew : list) { + for (JsonClient cnew : root.clients) { if (cnew.password == null || cnew.clientip == null) continue; // Invalid AvailableClient existing = clientPool.get(cnew.clientip); if (existing == null) { // New client - clientPool.put(cnew.clientip, new AvailableClient(cnew)); + AvailableClient newClient = new AvailableClient(cnew); + clientPool.put(cnew.clientip, newClient); + + for (JsonLocation loc : locationPool.values()) { + for (int id : loc.locationids) { + if (id == cnew.locationid) { + loc.clientList.add(newClient); + newClient.locationList.add(loc); + break; + } + } + } LOGGER.info("New client " + cnew.clientip); } else { existing.update(cnew); @@ -166,6 +245,9 @@ public class ConnectionManager { AvailableClient c = it.next(); if (c.isTimeout(NOW)) { LOGGER.info("Removing client " + c + " from list"); + for (JsonLocation loc : c.locationList) { + loc.clientList.remove(c); + } it.remove(); } -- cgit v1.2.3-55-g7522