diff --git a/guacamole/client/src/net/sourceforge/guacamole/Client.java b/guacamole/client/src/net/sourceforge/guacamole/Client.java index 5be1b9704..9eabf34e4 100644 --- a/guacamole/client/src/net/sourceforge/guacamole/Client.java +++ b/guacamole/client/src/net/sourceforge/guacamole/Client.java @@ -26,6 +26,7 @@ import net.sourceforge.guacamole.event.PointerEvent; public abstract class Client { + public abstract void ready() throws GuacamoleException; public abstract void send(KeyEvent event) throws GuacamoleException; public abstract void send(PointerEvent event) throws GuacamoleException; public abstract void setClipboard(String clipboard) throws GuacamoleException; diff --git a/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java b/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java index b94d8eee3..25a2ed99a 100644 --- a/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java +++ b/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java @@ -57,6 +57,17 @@ public class GuacamoleClient extends Client { } + public void ready() throws GuacamoleException { + + try { + output.write("ready;"); + output.flush(); + } + catch (IOException e) { + throw new GuacamoleException(e); + } + + } private static final int EVENT_DEADLINE = 500; diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java b/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java index a76060590..3075a2f3c 100644 --- a/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java +++ b/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java @@ -71,6 +71,10 @@ public class GuacamoleSession { client.setClipboard(clipboard); } + public void ready() throws GuacamoleException { + client.ready(); + } + public void disconnect() throws GuacamoleException { client.disconnect(); } diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/input/Ready.java b/guacamole/client/src/net/sourceforge/guacamole/net/input/Ready.java new file mode 100644 index 000000000..3603903d7 --- /dev/null +++ b/guacamole/client/src/net/sourceforge/guacamole/net/input/Ready.java @@ -0,0 +1,43 @@ + +package net.sourceforge.guacamole.net.input; + +/* + * 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 javax.servlet.ServletRequest; +import net.sourceforge.guacamole.GuacamoleException; +import org.w3c.dom.Element; + +import net.sourceforge.guacamole.net.GuacamoleSession; +import net.sourceforge.guacamole.net.XMLGuacamoleServlet; + +public class Ready extends XMLGuacamoleServlet { + + @Override + protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException { + + try { + session.getClient().ready(); + } + catch (GuacamoleException e) { + throw new GuacamoleException("Error updating ready status: " + e.getMessage(), e); + } + + } +} + diff --git a/guacamole/client/web/WEB-INF/web.xml b/guacamole/client/web/WEB-INF/web.xml index 6e54cf951..b8df34088 100644 --- a/guacamole/client/web/WEB-INF/web.xml +++ b/guacamole/client/web/WEB-INF/web.xml @@ -61,6 +61,15 @@ Clipboard /clipboard + + Client "ready-to-receive" heartbeat + Ready + net.sourceforge.guacamole.net.input.Ready + + + Ready + /ready + Key input servlet. Key diff --git a/guacamole/client/web/javascript/guacamole.js b/guacamole/client/web/javascript/guacamole.js index d5047c77a..1a076471d 100644 --- a/guacamole/client/web/javascript/guacamole.js +++ b/guacamole/client/web/javascript/guacamole.js @@ -540,7 +540,27 @@ function VNCClient(display) { handler(parameters); } - + + + function sendReady() { + + // Start heartbeat signal + var heartbeat = new XMLHttpRequest(); + heartbeat.open("GET", "ready"); + + heartbeat.onreadystatechange = function() { + + if (heartbeat != null && heartbeat.readyState >= 2) { + heartbeat = null; + setTimeout(sendReady, 50); + } + + }; + + heartbeat.send(); + + } + this.connect = function() { @@ -555,6 +575,7 @@ function VNCClient(display) { var message = new GuacamoleMessage(connect_xmlhttprequest.responseXML); if (!message.hasErrors()) { setState(STATE_WAITING); + sendReady(); handleResponse(makeRequest()); // Start stream if connection successful } else diff --git a/guacamole/proxy/client.c b/guacamole/proxy/client.c index 0a6b37d81..40a9792c4 100644 --- a/guacamole/proxy/client.c +++ b/guacamole/proxy/client.c @@ -85,12 +85,6 @@ void guac_start_client(guac_client* client) { /* VNC Client Loop */ for (;;) { - /* Handle server messages */ - if (client->handle_messages) { - client->handle_messages(client); - guac_flush(client->io); - } - wait_result = guac_instructions_waiting(io); if (wait_result > 0) { @@ -131,6 +125,12 @@ void guac_start_client(guac_client* client) { /* Otherwise, retval == 0 implies unfinished instruction */ + /* Handle server messages */ + if (client->handle_messages) { + client->handle_messages(client); + guac_flush(client->io); + } + } else if (wait_result < 0) return;