diff --git a/guacamole-common/src/main/java/net/sourceforge/guacamole/net/GuacamoleSession.java b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/GuacamoleSession.java
index 430a4aae5..7cd90d93a 100644
--- a/guacamole-common/src/main/java/net/sourceforge/guacamole/net/GuacamoleSession.java
+++ b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/GuacamoleSession.java
@@ -19,54 +19,16 @@ package net.sourceforge.guacamole.net;
* along with this program. If not, see .
*/
-import java.util.concurrent.locks.ReentrantLock;
+import net.sourceforge.guacamole.net.tunnel.GuacamoleTunnel;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-import net.sourceforge.guacamole.GuacamoleClient;
-import net.sourceforge.guacamole.GuacamoleTCPClient;
import net.sourceforge.guacamole.GuacamoleException;
public class GuacamoleSession {
private final HttpSession session;
- private SessionClient client;
- private ReentrantLock instructionStreamLock;
-
- public class SessionClient extends GuacamoleClient implements HttpSessionBindingListener {
-
- private GuacamoleClient client;
-
- public SessionClient(GuacamoleClient client) {
- this.client = client;
- }
-
- public void valueBound(HttpSessionBindingEvent event) {
- // Do nothing
- }
-
- public void valueUnbound(HttpSessionBindingEvent event) {
- try {
- disconnect();
- }
- catch (GuacamoleException e) {
- // Ignore
- }
- }
-
- public void write(char[] data, int off, int len) throws GuacamoleException {
- client.write(data, off, len);
- }
-
- public char[] read() throws GuacamoleException {
- return client.read();
- }
-
- public void disconnect() throws GuacamoleException {
- client.disconnect();
- }
-
- }
+ private ConcurrentMap tunnels;
public GuacamoleSession(HttpSession session) throws GuacamoleException {
@@ -77,57 +39,30 @@ public class GuacamoleSession {
synchronized (session) {
- client = (SessionClient) session.getAttribute("CLIENT");
- instructionStreamLock = (ReentrantLock) session.getAttribute("INSTRUCTION_STREAM_LOCK");
-
- }
-
- }
-
- public void attachClient(GuacamoleTCPClient client) throws GuacamoleException {
-
- synchronized (session) {
-
- this.client = new SessionClient(client);
- session.setAttribute("CLIENT", this.client);
-
- instructionStreamLock = new ReentrantLock();
- session.setAttribute("INSTRUCTION_STREAM_LOCK", instructionStreamLock);
-
- }
-
- }
-
- public SessionClient getClient() throws GuacamoleException {
- synchronized (session) {
-
- if (client == null)
- throw new GuacamoleException("Client not yet attached.");
-
- return client;
- }
- }
-
- public void invalidate() {
- session.invalidate();
- }
-
- public void detachClient() throws GuacamoleException {
-
- synchronized (session) {
-
- if (client != null) {
- client.disconnect();
- session.removeAttribute("CLIENT");
- client = null;
+ tunnels = (ConcurrentMap) session.getAttribute("GUAC_TUNNELS");
+ if (tunnels == null) {
+ tunnels = new ConcurrentHashMap();
+ session.setAttribute("GUAC_TUNNELS", tunnels);
}
}
}
- public ReentrantLock getInstructionStreamLock() {
- return instructionStreamLock;
+ public void invalidate() {
+ session.invalidate();
+ }
+
+ public void attachTunnel(GuacamoleTunnel tunnel) throws GuacamoleException {
+ tunnels.put(tunnel.getUUID().toString(), tunnel);
+ }
+
+ public void detachTunnel(GuacamoleTunnel tunnel) throws GuacamoleException {
+ tunnels.remove(tunnel.getUUID().toString());
+ }
+
+ public GuacamoleTunnel getTunnel(String tunnelUUID) {
+ return tunnels.get(tunnelUUID);
}
}
diff --git a/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnel.java b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnel.java
new file mode 100644
index 000000000..8f324141e
--- /dev/null
+++ b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnel.java
@@ -0,0 +1,53 @@
+
+package net.sourceforge.guacamole.net.tunnel;
+
+/*
+ * Guacamole - Clientless Remote Desktop
+ * Copyright (C) 2010 Michael Jumper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import java.util.UUID;
+import java.util.concurrent.locks.ReentrantLock;
+import net.sourceforge.guacamole.GuacamoleClient;
+import net.sourceforge.guacamole.GuacamoleException;
+
+public class GuacamoleTunnel {
+
+ private UUID uuid;
+ private GuacamoleClient client;
+ private ReentrantLock instructionStreamLock;
+
+ public GuacamoleTunnel(GuacamoleClient client) throws GuacamoleException {
+
+ this.client = client;
+ instructionStreamLock = new ReentrantLock();
+ uuid = UUID.randomUUID();
+
+ }
+
+ public GuacamoleClient getClient() throws GuacamoleException {
+ return client;
+ }
+
+ public ReentrantLock getInstructionStreamLock() {
+ return instructionStreamLock;
+ }
+
+ public UUID getUUID() {
+ return uuid;
+ }
+
+}
diff --git a/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnelServlet.java b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnelServlet.java
index 6a09fa0f7..fa270fc86 100644
--- a/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnelServlet.java
+++ b/guacamole-common/src/main/java/net/sourceforge/guacamole/net/tunnel/GuacamoleTunnelServlet.java
@@ -54,14 +54,25 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
if (query == null)
throw new GuacamoleException("No query string provided.");
- if (query.equals("connect"))
- doConnect(request, response);
+ if (query.equals("connect")) {
- else if(query.equals("read"))
- doRead(request, response);
+ GuacamoleTunnel tunnel = doConnect(request);
+ if (tunnel != null) {
+ try {
+ response.getWriter().println(tunnel.getUUID().toString());
+ }
+ catch (IOException e) {
+ throw new GuacamoleException(e);
+ }
+ }
- else if(query.equals("write"))
- doWrite(request, response);
+ }
+
+ else if(query.startsWith("read:"))
+ doRead(request, response, query.substring(5));
+
+ else if(query.startsWith("write:"))
+ doWrite(request, response, query.substring(6));
else
throw new GuacamoleException("Invalid tunnel operation: " + query);
@@ -72,14 +83,18 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
}
- protected abstract void doConnect(HttpServletRequest request, HttpServletResponse response) throws GuacamoleException;
+ protected abstract GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException;
- protected void doRead(HttpServletRequest request, HttpServletResponse response) throws GuacamoleException {
+ protected void doRead(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {
HttpSession httpSession = request.getSession(false);
GuacamoleSession session = new GuacamoleSession(httpSession);
- ReentrantLock instructionStreamLock = session.getInstructionStreamLock();
+ GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
+ if (tunnel == null)
+ throw new GuacamoleException("No such tunnel.");
+
+ ReentrantLock instructionStreamLock = tunnel.getInstructionStreamLock();
instructionStreamLock.lock();
try {
@@ -94,7 +109,7 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
try {
// Query new update from server
- GuacamoleClient client = session.getClient();
+ GuacamoleClient client = tunnel.getClient();
// For all messages, until another stream is ready (we send at least one message)
char[] message;
@@ -112,7 +127,7 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
}
if (message == null) {
- session.detachClient();
+ session.detachTunnel(tunnel);
throw new GuacamoleException("Disconnected.");
}
@@ -141,11 +156,15 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
}
- protected void doWrite(HttpServletRequest request, HttpServletResponse response) throws GuacamoleException {
+ protected void doWrite(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {
HttpSession httpSession = request.getSession(false);
GuacamoleSession session = new GuacamoleSession(httpSession);
+ GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
+ if (tunnel == null)
+ throw new GuacamoleException("No such tunnel.");
+
// We still need to set the content type to avoid the default of
// text/html, as such a content type would cause some browsers to
// attempt to parse the result, even though the JavaScript client
@@ -156,12 +175,14 @@ public abstract class GuacamoleTunnelServlet extends HttpServlet {
// Send data
try {
+ GuacamoleClient client = tunnel.getClient();
+
Reader input = request.getReader();
char[] buffer = new char[8192];
int length;
while ((length = input.read(buffer, 0, buffer.length)) != -1)
- session.getClient().write(buffer, 0, length);
+ client.write(buffer, 0, length);
}
catch (IOException e) {