summaryrefslogtreecommitdiffstats
path: root/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java')
-rw-r--r--src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java b/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java
new file mode 100644
index 0000000..0132e43
--- /dev/null
+++ b/src/main/java/de/bwlehrpool/bwlp_guac/ConnectionManager.java
@@ -0,0 +1,219 @@
+package de.bwlehrpool.bwlp_guac;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+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 javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Broker for all clients available.
+ * Keeps track of which clients are online, offline, assigned to a user etc.
+ */
+public class ConnectionManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);
+
+ // TODO: Config
+ private static final String SOURCE_URL = SlxConfig.clientListUrl();
+
+ private static final LinkedHashMap<String, AvailableClient> clientPool = new LinkedHashMap<String, AvailableClient>();
+
+ /**
+ * Pass plain user name, get existing connection (if any), or a fresh one
+ * @param user (LDAP) user name
+ */
+ public static WrappedConnection getForUser(String user) {
+ if (SOURCE_URL == null) {
+ LOGGER.warn("Don't have a source URL for client machines!");
+ return null;
+ }
+ try {
+ updateList();
+ // Find existing/free client
+ AvailableClient freeClient;
+ for (;;) {
+ freeClient = null;
+ synchronized (clientPool) {
+ for (AvailableClient ac : clientPool.values()) {
+ if (ac.isInUseBy(user)) {
+ freeClient = ac;
+ break;
+ }
+ }
+ if (freeClient == null) {
+ for (AvailableClient ac : clientPool.values()) {
+ if (ac.claim(user)) {
+ freeClient = ac;
+ break;
+ }
+ }
+ }
+ }
+ if (freeClient == null)
+ return null; // TODO: No more clients available -- how to handle?
+ // Found free or existing client, check if connection is (still) possible
+ if (freeClient.checkConnection(0)) {
+ LOGGER.info("Establishing mapping for user " + user + " to " + freeClient);
+ return freeClient.getConnection(user);
+ }
+ // Connection check failed - release and loop again
+ freeClient.releaseConnection(user);
+ }
+ } catch (Exception e) {
+ LOGGER.warn("KACKE AM DAMPFEN", e);
+ return null;
+ }
+ }
+
+ private static long lastUpdate = 0;
+
+ /**
+ * Fetch fresh client list from satellite server.
+ * Cache for 15 seconds.
+ */
+ private static synchronized void updateList() {
+ long now = System.currentTimeMillis();
+ if (now < lastUpdate) {
+ lastUpdate = now;
+ }
+ if (now - lastUpdate < 15000)
+ return;
+ // OK GO
+ lastUpdate = now;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(3000);
+ HttpURLConnection con;
+ try {
+ con = (HttpURLConnection) new URL(SOURCE_URL).openConnection();
+ } catch (MalformedURLException e1) {
+ LOGGER.warn("Bad Connection Pool URL", e1);
+ return;
+ } catch (IOException e1) {
+ LOGGER.warn("Cannot connect to Connection Pool URL", e1);
+ return;
+ }
+ if (con instanceof HttpsURLConnection) {
+ ((HttpsURLConnection) con).setHostnameVerifier(ignorer);
+ ((HttpsURLConnection) con).setSSLSocketFactory(sockFac);
+ }
+ try (BufferedInputStream in = new BufferedInputStream(con.getInputStream())) {
+ byte dataBuffer[] = new byte[2048];
+ int bytesRead;
+ while ((bytesRead = in.read(dataBuffer, 0, dataBuffer.length)) != -1) {
+ baos.write(dataBuffer, 0, bytesRead);
+ }
+ } catch (IOException e) {
+ LOGGER.warn("Error while reading reply of Connection Pool", e);
+ return;
+ }
+ populateList(baos.toByteArray());
+ }
+
+ private static void populateList(byte[] data) {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonClient[] list;
+ try {
+ list = mapper.readValue(data, JsonClient[].class);
+ } catch (Exception e) {
+ LOGGER.warn("Could not deserialize JSON from Connection Pool", e);
+ LOGGER.warn("Not updating local list");
+ return;
+ }
+ synchronized (clientPool) {
+ for (JsonClient cnew : list) {
+ 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));
+ LOGGER.info("New client " + cnew.clientip);
+ } else {
+ existing.update(cnew);
+ }
+ }
+ final long NOW = System.currentTimeMillis();
+ for (Iterator<AvailableClient> it = clientPool.values().iterator(); it.hasNext();) {
+ AvailableClient c = it.next();
+ if (c.isTimeout(NOW)) {
+ LOGGER.info("Removing client " + c + " from list");
+ it.remove();
+ }
+
+ }
+ LOGGER.info("List updated. " + clientPool.size() + " clients.");
+ }
+ }
+
+ /*
+ * Make SSL insecure
+ */
+
+ static {
+ SSLContext ctx = null;
+ try {
+ ctx = SSLContext.getInstance("TLSv1.2");
+ } catch (NoSuchAlgorithmException e) {
+ LOGGER.warn("Could not get TLSv1.2 context, SSL will be secure :-(", e);
+ }
+ if (ctx != null) {
+ try {
+ ctx.init(null, new TrustManager[] { new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ } }, null);
+ } catch (KeyManagementException e) {
+ LOGGER.warn("Could not initialize TLSv1.2 SSL context", e);
+ ctx = null;
+ }
+ }
+ if (ctx == null) {
+ sockFac = null;
+ } else {
+ sockFac = ctx.getSocketFactory();
+ }
+ }
+
+ private static final SSLSocketFactory sockFac;
+
+ private static final HostnameVerifier ignorer = new HostnameVerifier() {
+
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+
+}