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;