From ebb75a3494da00839db14fd13301448cd469d093 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 25 Jan 2012 18:34:56 -0800 Subject: [PATCH 1/3] Hackish support for loadable websocket servlets. --- .../net/basic/WebSocketSupportLoader.java | 98 +++++++++++++++++++ guacamole/src/main/webapp/WEB-INF/web.xml | 5 + 2 files changed, 103 insertions(+) create mode 100644 guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java new file mode 100644 index 000000000..b9670947a --- /dev/null +++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java @@ -0,0 +1,98 @@ +package net.sourceforge.guacamole.net.basic; + +/* + * 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import net.sourceforge.guacamole.GuacamoleException; + +/** + * Simple HttpServlet which outputs XML containing a list of all authorized + * configurations for the current user. + * + * @author Michael Jumper + */ +public class WebSocketSupportLoader implements ServletContextListener { + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + + try { + + // Attempt to find WebSocket servlet + Class servlet = (Class) GuacamoleClassLoader.getInstance().findClass( + "net.sourceforge.guacamole.net.basic.BasicGuacamoleTunnelServlet" + //"net.sourceforge.guacamole.net.basic.BasicGuacamoleWebSocketTunnelServlet" + ); + + // Dynamically add servlet IF SERVLET 3.0 API AVAILABLE! + try { + + // Get servlet registration class + Class regClass = Class.forName("javax.servlet.ServletRegistration"); + + // Get and invoke addServlet() + Method addServlet = ServletContext.class.getMethod("addServlet", String.class, Class.class); + Object reg = addServlet.invoke(sce.getServletContext(), "WebSocketTunnel", servlet); + + // Get and invoke addMapping() + Method addMapping = regClass.getMethod("addMapping", String[].class); + addMapping.invoke(reg, (Object) new String[]{"/websocket-tunnel"}); + + // If we succesfully load and register the WebSocket tunnel servlet, + // WebSocket is supported. + System.err.println("WebSocket support found!"); + + } + catch (ClassNotFoundException e) { + // Servlet API 3.0 unsupported + System.err.println("Servlet API 3.0 not found."); + } + catch (NoSuchMethodException e) { + // Servlet API 3.0 unsupported + System.err.println("Servlet API 3.0 not found."); + } + catch (IllegalAccessException e) { + } + catch (InvocationTargetException e) { + } + + } + catch (ClassNotFoundException e) { + + // If no such servlet class, WebSocket support not present + System.err.println("WebSocket support not found."); + + } + catch (GuacamoleException e) { + e.printStackTrace(); + } + + } + +} + diff --git a/guacamole/src/main/webapp/WEB-INF/web.xml b/guacamole/src/main/webapp/WEB-INF/web.xml index 041e82ce0..61ae0b21b 100644 --- a/guacamole/src/main/webapp/WEB-INF/web.xml +++ b/guacamole/src/main/webapp/WEB-INF/web.xml @@ -28,6 +28,11 @@ + + + net.sourceforge.guacamole.net.basic.WebSocketSupportLoader + + Login servlet. From b2704ffcad88b60ccd40a7a9bcf953c8a3317deb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 7 Mar 2012 20:29:41 -0800 Subject: [PATCH 2/3] Use logger, fix JavaDoc. --- .../net/basic/WebSocketSupportLoader.java | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java index b9670947a..550463716 100644 --- a/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java +++ b/guacamole/src/main/java/net/sourceforge/guacamole/net/basic/WebSocketSupportLoader.java @@ -25,15 +25,24 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import net.sourceforge.guacamole.GuacamoleException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Simple HttpServlet which outputs XML containing a list of all authorized - * configurations for the current user. + * Simple ServletContextListener which loads a WebSocket tunnel implementation + * if available, using the Servlet 3.0 API to dynamically load and install + * the tunnel servlet. + * + * Note that because Guacamole depends on the Servlet 2.5 API, and 3.0 may + * not be available or needed if WebSocket is not desired, the 3.0 API is + * detected and invoked dynamically via reflection. * * @author Michael Jumper */ public class WebSocketSupportLoader implements ServletContextListener { + private Logger logger = LoggerFactory.getLogger(WebSocketSupportLoader.class); + @Override public void contextDestroyed(ServletContextEvent sce) { } @@ -45,8 +54,7 @@ public class WebSocketSupportLoader implements ServletContextListener { // Attempt to find WebSocket servlet Class servlet = (Class) GuacamoleClassLoader.getInstance().findClass( - "net.sourceforge.guacamole.net.basic.BasicGuacamoleTunnelServlet" - //"net.sourceforge.guacamole.net.basic.BasicGuacamoleWebSocketTunnelServlet" + "net.sourceforge.guacamole.net.basic.BasicGuacamoleWebSocketTunnelServlet" ); // Dynamically add servlet IF SERVLET 3.0 API AVAILABLE! @@ -65,31 +73,36 @@ public class WebSocketSupportLoader implements ServletContextListener { // If we succesfully load and register the WebSocket tunnel servlet, // WebSocket is supported. - System.err.println("WebSocket support found!"); + logger.info("WebSocket support found and loaded."); } + + // Servlet API 3.0 unsupported catch (ClassNotFoundException e) { - // Servlet API 3.0 unsupported - System.err.println("Servlet API 3.0 not found."); + logger.error("Servlet API 3.0 not found.", e); } catch (NoSuchMethodException e) { - // Servlet API 3.0 unsupported - System.err.println("Servlet API 3.0 not found."); + logger.error("Servlet API 3.0 found, but incomplete.", e); } + + // Servlet API 3.0 found, but errors during use catch (IllegalAccessException e) { + logger.error("Unable to load WebSocket tunnel servlet.", e); } catch (InvocationTargetException e) { + logger.error("Internal error loading WebSocket tunnel servlet.", e); } } - catch (ClassNotFoundException e) { - - // If no such servlet class, WebSocket support not present - System.err.println("WebSocket support not found."); + // If no such servlet class, WebSocket support not present + catch (ClassNotFoundException e) { + logger.info("WebSocket support not found."); } + + // Log all GuacamoleExceptions catch (GuacamoleException e) { - e.printStackTrace(); + logger.error("Unable to load/detect WebSocket support.", e); } } From 7a266eb6b02e4fabd59fb92ea1e84b65dbe032af Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 8 Mar 2012 08:14:18 -0800 Subject: [PATCH 3/3] Using WebSocket tunnnel for connection (HTTP Tunnel temporarily disabled - need support detection) --- guacamole/src/main/webapp/client.xhtml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml index fb8c20c65..1a319ea11 100644 --- a/guacamole/src/main/webapp/client.xhtml +++ b/guacamole/src/main/webapp/client.xhtml @@ -101,10 +101,14 @@ window.onload = function() { window.setTimeout(function() { + var tunnel; + + // TODO: Detect WebSocket and websocket-tunnel + tunnel = new Guacamole.WebSocketTunnel("websocket-tunnel") + //tunnel = new Guacamole.HTTPTunnel("tunnel") + // Instantiate client - var guac = new Guacamole.Client( - new Guacamole.HTTPTunnel("tunnel") - ); + var guac = new Guacamole.Client(tunnel); // Add client to UI guac.getDisplay().className = "software-cursor";