Dear : I created a lab. I am using sample code :
public class DemoServlet extends GuacamoleHTTPTunnelServlet { private static final long serialVersionUID = 1L; private final Logger logger = LoggerFactory.getLogger(DemoServlet.class); public static SimpleGuacamoleTunnel tunnel = null; @Override protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException{ try { if( tunnel == null) { tunnel = inner(); } return tunnel; }catch(GuacamoleException e) { logger.error(e.getMessage(), e); throw e; }catch(Exception e) { logger.error(e.getMessage(), e); throw e; } } private static SimpleGuacamoleTunnel inner() throws GuacamoleException{ GuacamoleConfiguration config = new GuacamoleConfiguration(); config.setProtocol("rdp"); config.setParameter("hostname", "10.200.200.199"); config.setParameter("port", "3389"); config.setParameter("security", "nla"); config.setParameter("username", "admin"); config.setParameter("password", "P@ssw0rd"); config.setParameter("ignore-cert", "true"); config.setParameter("enable-drive", "true"); config.setParameter("drive-path", "/home/guacdshare"); config.setParameter("recording-path", "/anchor_dvr"); config.setParameter("create-recording-path", "true"); config.setParameter("recording-name", "test.guac"); InetGuacamoleSocket inet_socket = new InetGuacamoleSocket("10.200.200.200", 4822); GuacamoleSocket socket = new ConfiguredGuacamoleSocket(inet_socket,config); return new SimpleGuacamoleTunnel(socket); } } It is ok. I can connet to target from browser. Next, I try to extends【GuacamoleWebSocketTunnelEndpoint】 @ServerEndpoint ("/test_Tunnel") public class DemoEndPoint extends GuacamoleWebSocketTunnelEndpoint { @Override protected GuacamoleTunnel createTunnel(Session arg0, EndpointConfig arg1) throws GuacamoleException { *GuacamoleConfiguration target_config = Help.createGuacamoleConfiguration();* * GuacamoleClientInformation browser_config = **Help* *.createGuacamoleClientInformation();* * GuacamoleSocket gua_server_socket = **Help**.createInetGuacamoleSocket();* * ConfiguredGuacamoleSocket socket = new ConfiguredGuacamoleSocket( gua_server_socket, target_config, browser_config);* * GuacamoleTunnel tunnel = **Help**.assignGuacamoleTunnel(socket);* * return tunnel;* } } public class *Help*{ public static GuacamoleConfiguration *createGuacamoleConfiguration*(){ GuacamoleConfiguration config = new GuacamoleConfiguration(); config.setParameter("port", "3389"); config.setParameter("username", "admin"); config.setParameter("hostname", "10.200.200.199"); config.setParameter("ignore-cert", "true"); config.setParameter("security", "nla"); config.setParameter("password", "P@ssw0rd"); config.setProtocol("rdp"); return config; } public static GuacamoleClientInformation *createGuacamoleClientInformation* (){ GuacamoleClientInformation info = new GuacamoleClientInformation(); info.setOptimalScreenWidth(800); info.setOptimalScreenHeight(600); info.setOptimalResolution(72); return info; } public static InetGuacamoleSocket *createInetGuacamoleSocket*() throws GuacamoleException{ return new InetGuacamoleSocket("10.200.200.200", 4822); } public static GuacamoleTunnel *assignGuacamoleTunnel*(final GuacamoleSocket socket) { return new AbstractGuacamoleTunnel() { @Override public GuacamoleSocket getSocket() { return socket; } @Override public UUID getUUID() { return UUID.randomUUID(); } }; } } But I get a error, So i add logger at [ *GuacamoleWebSocketTunnelEndpoint*] @Override @OnOpen public void onOpen(final Session session, EndpointConfig config) { logger.error("into onOpen"); try { // Get tunnel tunnel = createTunnel(session, config); if (tunnel == null) { closeConnection(session, GuacamoleStatus.RESOURCE_NOT_FOUND); return; } } catch (GuacamoleException e) { logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage()); logger.debug("Error connecting WebSocket tunnel.", e); closeConnection(session, e.getStatus()); return; } // Manually register message handler session.addMessageHandler(new MessageHandler.Whole<String>() { @Override public void onMessage(String message) { GuacamoleWebSocketTunnelEndpoint.this.onMessage(message); } }); // Prepare read transfer thread Thread readThread = new Thread() { /** * Remote (client) side of this connection */ private final RemoteEndpoint.Basic remote = session.getBasicRemote(); @Override public void run() { logger.error("into run"); StringBuilder buffer = new StringBuilder(BUFFER_SIZE); GuacamoleReader reader = tunnel.acquireReader(); char[] readMessage; try { logger.error("point 1"); String text = null; { logger.error("point 1---- a"); String uuid = tunnel.getUUID().toString(); logger.error("point 1---- b"); String code = GuacamoleTunnel.INTERNAL_DATA_OPCODE; logger.error("point 1---- c"); GuacamoleInstruction lab = new GuacamoleInstruction(code, uuid); logger.error("point 1---- d"); text = lab.toString(); logger.error("point 1---- e"); } logger.error("remote class : {}", remote.getClass()); logger.error("text : {}", text); //tunnel close on this line. remote.sendText(text); logger.error("point 2"); try { logger.error("point 3"); // Attempt to read while ((readMessage = reader.read()) != null) { // Buffer message buffer.append(readMessage); // Flush if we expect to wait or buffer is getting full if (!reader.available() || buffer.length() >= BUFFER_SIZE) { remote.sendText(buffer.toString()); buffer.setLength(0); } } logger.error("point 4"); // No more data closeConnection(session, GuacamoleStatus.SUCCESS); logger.error("point 5"); } // Catch any thrown guacamole exception and attempt // to pass within the WebSocket connection, logging // each error appropriately. catch (GuacamoleClientException e) { logger.error("WebSocket connection terminated: {}", e.getMessage()); logger.error("WebSocket connection terminated due to client error.", e); closeConnection(session, e.getStatus()); } catch (GuacamoleConnectionClosedException e) { logger.error("Connection to guacd closed.", e); closeConnection(session, GuacamoleStatus.SUCCESS); } catch (GuacamoleException e) { logger.error("Connection to guacd terminated abnormally: {}", e.getMessage()); logger.error("Internal error during connection to guacd.", e); closeConnection(session, e.getStatus()); } logger.error("point 6"); } catch (IOException e) { logger.error("I/O error prevents further reads.", e); closeConnection(session, GuacamoleStatus.SERVER_ERROR); }catch (Exception e) { logger.error(e.getMessage(), e); closeConnection(session, GuacamoleStatus.SERVER_ERROR); }finally { logger.error("out run"); } } }; readThread.start(); } *Logger content is : * [11:37:14.552][http-nio-443-exec-7][DEBUG][org.apache.guacamole.net.InetGuacamoleSocket:90]【Connecting to guacd at 10.200.200.200:4822.】 [11:37:14.571][http-nio-443-exec-7][ERROR][org.apache.guacamole.protocol.ConfiguredGuacamoleSocket:135]【無connection ID, 走getProtocal()路線】 [11:37:14.571][http-nio-443-exec-7][ERROR][org.apache.guacamole.protocol.ConfiguredGuacamoleSocket:141]【最後select_arg的結果 : rdp】 [11:37:14.585][http-nio-443-exec-7][ERROR][org.apache.guacamole.protocol.ConfiguredGuacamoleSocket:199]【arg_values : [10.200.200.199, 3389, , admin, P@ssw0rd, , , , , , , , , , , , , , nla, true, , , , , , , , , , , , , , , , , , , , , , , , , , , , ]】 [11:37:14.614][http-nio-443-exec-7][ERROR][org.apache.guacamole.protocol.ConfiguredGuacamoleSocket:211]【id : $f99d685d-ac59-4bd2-b06f-48bce3a3c66b】 [11:37:14.614][http-nio-443-exec-7][ERROR][help.Help$1:54]【into AbstractGuacamoleTunnel】 [11:37:14.630][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:144]【into run】 [11:37:14.630][Thread-6][ERROR][help.Help$1:68]【into acquireReader】 [11:37:14.630][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:150]【point 1】 [11:37:14.630][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:154]【point 1---- a】 [11:37:14.630][Thread-6][ERROR][help.Help:59]【into getUUID】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:156]【point 1---- b】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:158]【point 1---- c】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:160]【point 1---- d】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:162]【point 1---- e】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:166]【remote class : class org.apache.tomcat.websocket.WsRemoteEndpointBasic】 [11:37:14.645][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:169]【text : 0.,36.4045a0fa-c415-473f-938a-ba0b116b86c1;】 [11:37:14.645][http-nio-443-exec-4][ERROR][org.apache.guacamole.websocket.*GuacamoleWebSocketTunnelEndpoint:261]【into onClose】* [11:37:14.661][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:220]【Deflater has been closed】 java.lang.NullPointerException: Deflater has been closed at java.util.zip.Deflater.ensureOpen(Unknown Source) ~[na:1.7.0_79] at java.util.zip.Deflater.deflate(Unknown Source) ~[na:1.7.0_79] at org.apache.tomcat.websocket.PerMessageDeflate.sendMessagePart(PerMessageDeflate.java:345) ~[tomcat-websocket.jar:8.0.36] at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:300) ~[tomcat-websocket.jar:8.0.36] at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$TextMessageSendHandler.write(WsRemoteEndpointImplBase.java:759) ~[tomcat-websocket.jar:8.0.36] at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialString(WsRemoteEndpointImplBase.java:252) ~[tomcat-websocket.jar:8.0.36] at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendString(WsRemoteEndpointImplBase.java:195) ~[tomcat-websocket.jar:8.0.36] at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:37) ~[tomcat-websocket.jar:8.0.36] at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$2.run(GuacamoleWebSocketTunnelEndpoint.java:172) ~[guacamole-common-0.9.13-incubating.jar:na] [11:37:14.661][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:76]【into closeConnection】 [11:37:14.661][Thread-6][ERROR][org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint:223]【out run】 I don't know why tunnel run close method.... I need help . thanks On Browser Side JavaScript file (which is named lab.js) (function(window){ "use strict"; window.lab = { save : function(key, API){ this[key] = API; }, exports : function(key){ return this[key]; } }; }(window)); (function(window, alert, Guacamole, lab){ "use strict"; function create_gua_client( path, place ){ var websocket_tunnel = new Guacamole.WebSocketTunnel(path); var guac_client = new Guacamole.Client(websocket_tunnel); var display = document.getElementById( place ); display.appendChild(guac_client.getDisplay().getElement()); guac_client.onerror = function(error) { alert(error); }; window.onunload = function() { guac_client.disconnect(); }; return { client : guac_client, play_element : guac_client.getDisplay().getElement(), root_element : display, }; } lab.save("create_gua_client", create_gua_client); }(window, window.alert, window.Guacamole, window.lab)); (function(window, Guacamole, lab){ "use strict"; function register_mouse( gua_client ){ var mouse = new Guacamole.Mouse(gua_client.client.getDisplay().getElement()); mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = function(mouseState) { gua_client.client.sendMouseState(mouseState); }; } lab.save("register_mouse", register_mouse); }(window, window.Guacamole, window.lab)); (function(window, Guacamole, lab){ "use strict"; function register_keyboard( gua_client ){ var keyboard = new Guacamole.Keyboard(document.getElementById("body")); keyboard.onkeydown = function(keysym) { gua_client.client.sendKeyEvent(1, keysym); return true; }; keyboard.onkeyup = function(keysym) { gua_client.client.sendKeyEvent(0, keysym); return true; }; } lab.save("register_keyboard", register_keyboard); }(window, window.Guacamole, window.lab)); (function(window, Guacamole, lab){ "use strict"; function register_touch_screen( gua_client ){ var touchScreen = new Guacamole.Mouse.Touchscreen(gua_client.play_element); touchScreen.onmousedown = touchScreen.onmousemove = touchScreen.onmouseup = function(mouseState) { gua_client.client.sendMouseState(mouseState); }; } lab.save("register_touch_screen", register_touch_screen); }(window, window.Guacamole, window.lab)); (function(window, $, Guacamole, lab){ "use strict"; function register_on_screen_keyboard( gua_client ){ var keyboard = new Guacamole.OnScreenKeyboard(lab.keyJson); keyboard.onkeydown = function(keysym) { gua_client.client.sendKeyEvent(1, keysym); return true; }; keyboard.onkeyup = function(keysym) { gua_client.client.sendKeyEvent(0, keysym); return true; }; $(".osk").bind("blur", function(){ keyboard.reset(); }); $(".osk").append(keyboard.getElement()); keyboard.resize(600); } lab.save("register_on_screen_keyboard", register_on_screen_keyboard); }(window, window.$, window.Guacamole, window.lab)); (function(window, Guacamole, lab){ "use strict"; function connect( gua_client, query_string ){ gua_client.client.connect(query_string); } lab.save("connect", connect); }(window, window.Guacamole, window.lab)); (function(window, Guacamole, lab){ "use strict"; var create_gua_client = lab.exports("create_gua_client"); var register_mouse = lab.exports("register_mouse"); var register_keyboard = lab.exports("register_keyboard"); var register_touch_screen = lab.exports("register_touch_screen"); var register_on_screen_keyboard = lab.exports("register_on_screen_keyboard"); var connect = lab.exports("connect"); function start( path, place ){ var client = create_gua_client(path, place); register_mouse(client); register_keyboard(client); register_touch_screen(client); register_on_screen_keyboard(client); connect(client, "anQueryString"); } lab.save("start", start); }(window, window.Guacamole, window.lab)); *Html code is* <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel=stylesheet type="text/css" href="./css/core/guacamole.css"> <style> .resize-sensor { height: 100%; width: 100%; position: absolute; left: 0; top: 0; overflow: hidden; border: none; } </style> </head> <body id="body"> <!-- style="width:600px;height:480px;overflow: auto;" --> <div style="margin:50px 0 0 50px;"> <div id="displayPlace" ></div> </div> <div style="margin:50px 0 0 50px;"> <div class="osk" style="width:600px;"> </div> </div> </body> <script type="text/javascript" src="./js/core/all.js"></script> <script type="text/javascript" src="./js/third/jquery-3.2.1.min.js"></script> <script type="text/javascript" src="./js/rd2/lab.js"></script> <script type="text/javascript" src="./js/rd2/lab_depend.js"></script> <script type="text/javascript"> (function(window, lab){ var start = lab.exports("start"); $(function(){ start("test_Tunnel", "displayPlace"); }); }(window, window.lab)); </script> </html> Thanks.