diff --git a/guacamole/client/src/net/sourceforge/guacamole/Client.java b/guacamole/client/src/net/sourceforge/guacamole/Client.java
index 5be1b9704..93000aaf4 100644
--- a/guacamole/client/src/net/sourceforge/guacamole/Client.java
+++ b/guacamole/client/src/net/sourceforge/guacamole/Client.java
@@ -19,17 +19,14 @@ package net.sourceforge.guacamole;
* along with this program. If not, see .
*/
-import net.sourceforge.guacamole.instruction.Instruction;
import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.event.KeyEvent;
import net.sourceforge.guacamole.event.PointerEvent;
public abstract class Client {
- public abstract void send(KeyEvent event) throws GuacamoleException;
- public abstract void send(PointerEvent event) throws GuacamoleException;
- public abstract void setClipboard(String clipboard) throws GuacamoleException;
+ public abstract void write(char[] chunk, int off, int len) throws GuacamoleException;
+ public abstract char[] read() throws GuacamoleException;
public abstract void disconnect() throws GuacamoleException;
- public abstract Instruction nextInstruction(boolean blocking) throws GuacamoleException;
}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java b/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java
index a2cbc40b3..f79e8a1b4 100644
--- a/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java
+++ b/guacamole/client/src/net/sourceforge/guacamole/GuacamoleClient.java
@@ -31,7 +31,6 @@ import java.io.OutputStream;
import java.io.Writer;
import java.io.OutputStreamWriter;
-import net.sourceforge.guacamole.instruction.Instruction;
import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.event.EventQueue;
import net.sourceforge.guacamole.event.EventHandler;
@@ -57,64 +56,9 @@ public class GuacamoleClient extends Client {
}
-
- private static final int EVENT_DEADLINE = 500;
-
- private EventQueue keyEvents = new EventQueue(new EventHandler() {
-
- public void handle(KeyEvent event) throws IOException {
- int pressed = 0;
- if (event.getPressed()) pressed = 1;
-
- output.write("key:" + event.getKeySym() + "," + pressed + ";");
- output.flush();
- }
-
- }, EVENT_DEADLINE);
-
- private EventQueue pointerEvents = new EventQueue(new EventHandler() {
-
- public void handle(PointerEvent event) throws IOException {
- int mask = 0;
- if (event.isLeftButtonPressed()) mask |= 1;
- if (event.isMiddleButtonPressed()) mask |= 2;
- if (event.isRightButtonPressed()) mask |= 4;
- if (event.isUpButtonPressed()) mask |= 8;
- if (event.isDownButtonPressed()) mask |= 16;
-
-
- output.write("mouse:" + event.getX() + "," + event.getY() + "," + mask + ";");
- output.flush();
- }
-
- }, EVENT_DEADLINE);
-
-
- public void send(KeyEvent event) throws GuacamoleException {
-
+ public void write(char[] chunk, int off, int len) throws GuacamoleException {
try {
- keyEvents.add(event);
- }
- catch (IOException e) {
- throw new GuacamoleException(e);
- }
-
- }
-
- public void send(PointerEvent event) throws GuacamoleException {
-
- try {
- pointerEvents.add(event);
- }
- catch (IOException e) {
- throw new GuacamoleException(e);
- }
-
- }
-
- public void setClipboard(String clipboard) throws GuacamoleException {
- try {
- output.write("clipboard:" + Instruction.escape(clipboard) + ";");
+ output.write(chunk, off, len);
output.flush();
}
catch (IOException e) {
@@ -134,7 +78,7 @@ public class GuacamoleClient extends Client {
private int usedLength = 0;
private char[] buffer = new char[20000];
- public Instruction nextInstruction(boolean blocking) throws GuacamoleException {
+ public char[] read() throws GuacamoleException {
try {
@@ -164,20 +108,15 @@ public class GuacamoleClient extends Client {
if (readChar == ';') {
// Get instruction
- final String instruction = new String(buffer, 0, i+1);
+ char[] chunk = new char[i+1];
+ System.arraycopy(buffer, 0, chunk, 0, i+1);
// Reset buffer
usedLength -= i+1;
System.arraycopy(buffer, i+1, buffer, 0, usedLength);
- // Return instruction string wrapped in Instruction class
- return new Instruction() {
-
- public String toString() {
- return instruction;
- }
-
- };
+ // Return instruction string
+ return chunk;
}
}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/ClipboardInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/ClipboardInstruction.java
deleted file mode 100644
index 5eb29737b..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/ClipboardInstruction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-
-package net.sourceforge.guacamole.instruction;
-
-/*
- * 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 .
- */
-
-public class ClipboardInstruction extends Instruction {
-
- private String data;
-
- public ClipboardInstruction(String data) {
- this.data = data;
- }
-
- public String getData() {
- return data;
- }
-
- @Override
- public String toString() {
- return "clipboard:" + escape(getData()) + ";";
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/ErrorInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/ErrorInstruction.java
deleted file mode 100644
index acc550777..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/ErrorInstruction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-
-package net.sourceforge.guacamole.instruction;
-
-/*
- * 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 .
- */
-
-public class ErrorInstruction extends Instruction {
-
- private String error;
-
- public ErrorInstruction(String error) {
- this.error = error;
- }
-
- public String getError() {
- return error;
- }
-
- @Override
- public String toString() {
- return "error:" + escape(getError()) + ";";
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/Instruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/Instruction.java
deleted file mode 100644
index 81e506e60..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/Instruction.java
+++ /dev/null
@@ -1,63 +0,0 @@
-
-package net.sourceforge.guacamole.instruction;
-
-/*
- * 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 .
- */
-
-public abstract class Instruction {
-
-
- // All Instructions must provide a toString() implementation
- // which returns the properly formatted instruction:
- // OPCODE:parm1,parm2,...,parmN;
-
- @Override
- public abstract String toString();
-
- public static String escape(String str) {
-
- StringBuffer sb = new StringBuffer();
-
- for (int i=0; i.
- */
-
-public class NameInstruction extends Instruction {
-
- private String name;
-
- public NameInstruction(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public String toString() {
- return "name:" + escape(getName()) + ";";
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/SizeInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/SizeInstruction.java
deleted file mode 100644
index e21364469..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/SizeInstruction.java
+++ /dev/null
@@ -1,47 +0,0 @@
-
-package net.sourceforge.guacamole.instruction;
-
-/*
- * 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 .
- */
-
-public class SizeInstruction extends Instruction {
-
- private int width;
- private int height;
-
- public SizeInstruction(int width, int height) {
- this.width = width;
- this.height = height;
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- @Override
- public String toString() {
- return "size:"
- + getWidth() + ","
- + getHeight() + ";";
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CopyRectInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CopyRectInstruction.java
deleted file mode 100644
index 1b23f7777..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CopyRectInstruction.java
+++ /dev/null
@@ -1,78 +0,0 @@
-
-package net.sourceforge.guacamole.instruction.framebuffer;
-
-/*
- * 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 net.sourceforge.guacamole.instruction.Instruction;
-
-public class CopyRectInstruction extends Instruction {
-
- private final int x;
- private final int y;
- private final int width;
- private final int height;
-
- private final int srcX;
- private final int srcY;
-
- public CopyRectInstruction(int x, int y, int width, int height, int srcX, int srcY) {
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- this.srcX = srcX;
- this.srcY = srcY;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public int getSrcX() {
- return srcX;
- }
-
- public int getSrcY() {
- return srcY;
- }
-
- @Override
- public String toString() {
- return "copy:"
- + getSrcX() + ","
- + getSrcY() + ","
- + getWidth() + ","
- + getHeight() + ","
- + getX() + ","
- + getY() + ";";
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CursorInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CursorInstruction.java
deleted file mode 100644
index b5cbe656f..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/CursorInstruction.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package net.sourceforge.guacamole.instruction.framebuffer;
-
-import net.sourceforge.guacamole.net.Base64;
-
-/*
- * 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 net.sourceforge.guacamole.instruction.Instruction;
-
-public class CursorInstruction extends Instruction {
-
- private int x;
- private int y;
- private PNGImage image;
-
- public CursorInstruction(int x, int y, PNGImage image) {
- this.x = x;
- this.y = y;
- this.image = image;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public PNGImage getImage() {
- return image;
- }
-
- public int getWidth() {
- return getImage().getWidth();
- }
-
- public int getHeight() {
- return getImage().getHeight();
- }
-
- @Override
- public String toString() {
- return "cursor:"
- + getX() + ","
- + getY() + ","
- + Base64.toString(getImage().getData()) + ";";
- }
-
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/DrawRectInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/DrawRectInstruction.java
deleted file mode 100644
index 544aed334..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/DrawRectInstruction.java
+++ /dev/null
@@ -1,72 +0,0 @@
-
-package net.sourceforge.guacamole.instruction.framebuffer;
-
-/*
- * 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 net.sourceforge.guacamole.instruction.Instruction;
-
-public class DrawRectInstruction extends Instruction {
-
- private final int x;
- private final int y;
- private final int width;
- private final int height;
- private final int color;
-
- public DrawRectInstruction(int x, int y, int width, int height, int color) {
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- this.color = color;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public int getColor() {
- return color;
- }
-
- @Override
- public String toString() {
-
- return "rect:"
- + getX() + ","
- + getY() + ","
- + getWidth() + ","
- + getHeight() + ","
- + String.format("#%06X", getColor()) + ";";
-
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGImage.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGImage.java
deleted file mode 100644
index 79489dfd3..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGImage.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package net.sourceforge.guacamole.instruction.framebuffer;
-
-/*
- * 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.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Iterator;
-import javax.imageio.IIOImage;
-import javax.imageio.ImageIO;
-import javax.imageio.ImageWriter;
-import javax.imageio.stream.ImageOutputStream;
-import net.sourceforge.guacamole.GuacamoleException;
-
-public class PNGImage {
-
- private int width;
- private int height;
- private byte[] data;
-
- public PNGImage(BufferedImage image) throws GuacamoleException {
-
- width = image.getWidth();
- height = image.getHeight();
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
- try {
- writeImage(image, bos);
- bos.flush();
- }
- catch (IOException e) {
- throw new GuacamoleException("I/O Error while creating PNG.", e);
- }
-
- data = bos.toByteArray();
- }
-
- public byte[] getData() {
- return data;
- }
-
- public int getHeight() {
- return height;
- }
-
- public int getWidth() {
- return width;
- }
-
- private static void writeImage(BufferedImage image, OutputStream outputStream) throws GuacamoleException, IOException {
-
- // Obtain list of image writers
- // If no such writers exist, fail with error, exit.
- Iterator writers = ImageIO.getImageWritersByMIMEType("image/png");
- if (!writers.hasNext())
- throw new GuacamoleException("No useful image writers found.");
-
- // Obtain JPEG writer
- ImageWriter imageWriter = writers.next();
-
- // Setup image parameters (including compression quality)
- /*ImageWriteParam imageParameters = new JPEGImageWriteParam(Locale.ENGLISH);
- imageParameters.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- imageParameters.setCompressionQuality(0.6f); // 60% quality, currently...
- imageParameters.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);*/
-
- ImageOutputStream out = ImageIO.createImageOutputStream(outputStream);
-
- // Write image
- imageWriter.setOutput(out);
- imageWriter.write(null, new IIOImage(image, null, null), null/*imageParameters*/);
- imageWriter.dispose();
-
- out.flush();
- }
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGInstruction.java b/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGInstruction.java
deleted file mode 100644
index 4d5e26962..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/instruction/framebuffer/PNGInstruction.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package net.sourceforge.guacamole.instruction.framebuffer;
-
-/*
- * 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 net.sourceforge.guacamole.instruction.Instruction;
-import net.sourceforge.guacamole.net.Base64;
-
-public class PNGInstruction extends Instruction {
-
- private int x;
- private int y;
- private PNGImage image;
-
- public PNGInstruction(int x, int y, PNGImage image) {
- this.x = x;
- this.y = y;
- this.image = image;
- }
-
- public int getX() {
- return x;
- }
-
- public int getY() {
- return y;
- }
-
- public PNGImage getImage() {
- return image;
- }
-
- public int getWidth() {
- return getImage().getWidth();
- }
-
- public int getHeight() {
- return getImage().getHeight();
- }
-
- @Override
- public String toString() {
- return "png:"
- + getX() + ","
- + getY() + ","
- + Base64.toString(getImage().getData()) + ";";
- }
-
-
-}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java b/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
index a76060590..52a7d0ac6 100644
--- a/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
+++ b/guacamole/client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
@@ -27,7 +27,6 @@ import javax.servlet.http.HttpSessionBindingListener;
import net.sourceforge.guacamole.Client;
import net.sourceforge.guacamole.GuacamoleClient;
import net.sourceforge.guacamole.GuacamoleException;
-import net.sourceforge.guacamole.instruction.Instruction;
import net.sourceforge.guacamole.event.KeyEvent;
import net.sourceforge.guacamole.event.PointerEvent;
@@ -59,26 +58,18 @@ public class GuacamoleSession {
}
}
- public void send(KeyEvent event) throws GuacamoleException {
- client.send(event);
+ public void write(char[] data, int off, int len) throws GuacamoleException {
+ client.write(data, off, len);
}
- public void send(PointerEvent event) throws GuacamoleException {
- client.send(event);
- }
-
- public void setClipboard(String clipboard) throws GuacamoleException {
- client.setClipboard(clipboard);
+ public char[] read() throws GuacamoleException {
+ return client.read();
}
public void disconnect() throws GuacamoleException {
client.disconnect();
}
- public Instruction nextInstruction(boolean blocking) throws GuacamoleException {
- return client.nextInstruction(blocking);
- }
-
}
public GuacamoleSession(HttpSession session) throws GuacamoleException {
diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/input/Clipboard.java b/guacamole/client/src/net/sourceforge/guacamole/net/input/Inbound.java
similarity index 63%
rename from guacamole/client/src/net/sourceforge/guacamole/net/input/Clipboard.java
rename to guacamole/client/src/net/sourceforge/guacamole/net/input/Inbound.java
index ec299061a..4d3429410 100644
--- a/guacamole/client/src/net/sourceforge/guacamole/net/input/Clipboard.java
+++ b/guacamole/client/src/net/sourceforge/guacamole/net/input/Inbound.java
@@ -1,4 +1,3 @@
-
package net.sourceforge.guacamole.net.input;
/*
@@ -23,46 +22,37 @@ import javax.servlet.ServletRequest;
import net.sourceforge.guacamole.GuacamoleException;
import org.w3c.dom.Element;
+import java.io.Reader;
+import java.io.IOException;
+
import net.sourceforge.guacamole.net.GuacamoleSession;
import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
-import java.io.IOException;
-import java.io.Reader;
+public class Inbound extends XMLGuacamoleServlet {
-/**
- * Servlet which sets the clipboard data.
- *
- * This servlet takes one parameter:
- * data: The data to set the clipboard to.
- *
- * @author Michael Jumper
- */
-
-public class Clipboard extends XMLGuacamoleServlet {
@Override
protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
+ // Send data
try {
- // Read data from request body
- Reader reader = request.getReader();
- StringBuilder data = new StringBuilder();
+ Reader input = request.getReader();
+ char[] buffer = new char[8192];
- int codepoint;
- while ((codepoint = reader.read()) != -1)
- data.appendCodePoint(codepoint);
+ int length;
+ while ((length = input.read(buffer, 0, buffer.length)) != -1)
+ session.getClient().write(buffer, 0, length);
- // Set clipboard
- session.getClient().setClipboard(data.toString());
}
catch (IOException e) {
- throw new GuacamoleException("I/O error sending clipboard to server: " + e.getMessage(), e);
+ throw new GuacamoleException("I/O Error sending data to server: " + e.getMessage(), e);
}
catch (GuacamoleException e) {
- throw new GuacamoleException("Error sending clipboard to server: " + e.getMessage(), e);
+ throw new GuacamoleException("Error sending data to server: " + e.getMessage(), e);
}
}
+
}
diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/input/Key.java b/guacamole/client/src/net/sourceforge/guacamole/net/input/Key.java
deleted file mode 100644
index 9e5b80fdb..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/net/input/Key.java
+++ /dev/null
@@ -1,66 +0,0 @@
-
-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.event.KeyEvent;
-
-import net.sourceforge.guacamole.net.GuacamoleSession;
-import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
-
-/**
- * Servlet which accepts keyboard input events, forwards these events to the
- * client associated with the session, and returns the result (if any)
- * to the HTTP client via XML.
- *
- * This servlet takes three parameters:
- * index: The event index. As HTTP requests may arrive out of order,
- * this index provides the event queue with a means of sorting
- * events, and determining if events are missing. The first
- * event has index 0.
- * pressed: Whether the key was pressed (1) or released (0).
- * keysym: The integer representing the corresponding X11 keysym.
- *
- * @author Michael Jumper
- */
-
-public class Key extends XMLGuacamoleServlet {
-
- @Override
- protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
-
- // Event parameters
- int index = Integer.parseInt(request.getParameter("index"));
- boolean pressed = request.getParameter("pressed").equals("1");
- int keysym = Integer.parseInt(request.getParameter("keysym"));
-
- // Send/queue event
- try {
- session.getClient().send(new KeyEvent(index, keysym, pressed));
- }
- catch (GuacamoleException e) {
- throw new GuacamoleException("Error sending key event to server: " + e.getMessage(), e);
- }
-
- }
-}
-
diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/input/Pointer.java b/guacamole/client/src/net/sourceforge/guacamole/net/input/Pointer.java
deleted file mode 100644
index 52ccaacb6..000000000
--- a/guacamole/client/src/net/sourceforge/guacamole/net/input/Pointer.java
+++ /dev/null
@@ -1,63 +0,0 @@
-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.event.PointerEvent;
-
-import net.sourceforge.guacamole.net.GuacamoleSession;
-import net.sourceforge.guacamole.net.XMLGuacamoleServlet;
-
-public class Pointer extends XMLGuacamoleServlet {
-
-
- @Override
- protected void handleRequest(GuacamoleSession session, ServletRequest request, Element root) throws GuacamoleException {
- // Event parameters
- String[] events = request.getParameterValues("event");
-
- for (String event : events) {
-
- String[] parameters = event.split(",");
-
- int index = Integer.parseInt(parameters[0]);
-
- int x = Integer.parseInt(parameters[1]);
- int y = Integer.parseInt(parameters[2]);
-
- boolean left = parameters[3].equals("1");
- boolean middle = parameters[4].equals("1");
- boolean right = parameters[5].equals("1");
- boolean up = parameters[6].equals("1");
- boolean down = parameters[7].equals("1");
-
- // Store event
- try {
- session.getClient().send(new PointerEvent(index, left, middle, right, up, down, x, y));
- }
- catch (GuacamoleException e) {
- throw new GuacamoleException("Error sending pointer event to server: " + e.getMessage(), e);
- }
- }
- }
-
-}
-
diff --git a/guacamole/client/src/net/sourceforge/guacamole/net/output/InstructionStream.java b/guacamole/client/src/net/sourceforge/guacamole/net/output/InstructionStream.java
index 6a66c2c7d..33237d44a 100644
--- a/guacamole/client/src/net/sourceforge/guacamole/net/output/InstructionStream.java
+++ b/guacamole/client/src/net/sourceforge/guacamole/net/output/InstructionStream.java
@@ -18,12 +18,9 @@ package net.sourceforge.guacamole.net.output;
* along with this program. If not, see .
*/
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
+import java.io.Writer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.GZIPOutputStream;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -31,8 +28,6 @@ import net.sourceforge.guacamole.Client;
import net.sourceforge.guacamole.net.GuacamoleServlet;
import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSession;
-import net.sourceforge.guacamole.instruction.Instruction;
-import net.sourceforge.guacamole.instruction.ErrorInstruction;
public class InstructionStream extends GuacamoleServlet {
@@ -46,36 +41,7 @@ public class InstructionStream extends GuacamoleServlet {
try {
response.setContentType("text/plain");
- OutputStream out = response.getOutputStream();
-
- // Compress if enabled and supported by browser
- if (session.getConfiguration().getCompressStream()) {
-
- String encodingHeader = request.getHeader("Accept-Encoding");
- if (encodingHeader != null) {
-
- String[] encodings = encodingHeader.split(",");
- for (String encoding : encodings) {
-
- // Use gzip if supported
- if (encoding.equals("gzip")) {
- response.setHeader("Content-Encoding", "gzip");
- out = new GZIPOutputStream(out);
- break;
- }
-
- // Use deflate if supported
- if (encoding.equals("deflate")) {
- response.setHeader("Content-Encoding", "deflate");
- out = new DeflaterOutputStream(out);
- break;
- }
-
- }
-
- }
-
- }
+ Writer out = response.getWriter();
try {
@@ -83,12 +49,11 @@ public class InstructionStream extends GuacamoleServlet {
Client client = session.getClient();
// For all messages, until another stream is ready (we send at least one message)
- Instruction message = client.nextInstruction(true); // Block until first message is read
- while (message != null) {
+ char[] message;
+ while ((message = client.read()) != null) {
// Get message output bytes
- byte[] outputBytes = message.toString().getBytes("UTF-8");
- out.write(outputBytes);
+ out.write(message, 0, message.length);
out.flush();
response.flushBuffer();
@@ -96,14 +61,11 @@ public class InstructionStream extends GuacamoleServlet {
if (instructionStreamLock.hasQueuedThreads())
break;
- message = client.nextInstruction(false); // Read remaining messages, do not block.
}
}
catch (GuacamoleException e) {
- Instruction message = new ErrorInstruction(e.getMessage());
- byte[] outputBytes = message.toString().getBytes("UTF-8");
- out.write(outputBytes);
+ out.write("error:" + e.getMessage() + ";");
out.flush();
response.flushBuffer();
}
diff --git a/guacamole/client/web/WEB-INF/web.xml b/guacamole/client/web/WEB-INF/web.xml
index 6e54cf951..f46926389 100644
--- a/guacamole/client/web/WEB-INF/web.xml
+++ b/guacamole/client/web/WEB-INF/web.xml
@@ -53,31 +53,13 @@
/instructions
- Clipboard input servlet.
- Clipboard
- net.sourceforge.guacamole.net.input.Clipboard
+ Input servlet.
+ Inbound
+ net.sourceforge.guacamole.net.input.Inbound
- Clipboard
- /clipboard
-
-
- Key input servlet.
- Key
- net.sourceforge.guacamole.net.input.Key
-
-
- Key
- /key
-
-
- Pointer input servlet.
- Pointer
- net.sourceforge.guacamole.net.input.Pointer
-
-
- Pointer
- /pointer
+ Inbound
+ /inbound
Guacamole Access Restrictions
diff --git a/guacamole/client/web/javascript/guacamole.js b/guacamole/client/web/javascript/guacamole.js
index fe2006bb5..83a65991a 100644
--- a/guacamole/client/web/javascript/guacamole.js
+++ b/guacamole/client/web/javascript/guacamole.js
@@ -46,9 +46,6 @@ function VNCClient(display) {
|| currentState == STATE_WAITING;
}
- var keyIndex = 0;
- var xmlIndex = 0;
-
// Layers
var background = null;
var cursor = null;
@@ -118,17 +115,7 @@ function VNCClient(display) {
this.enableKeyboard();
function sendKeyEvent(pressed, keysym) {
-
- // Do not send requests if not connected
- if (!isConnected())
- return;
-
- var key_xmlhttprequest = new XMLHttpRequest();
- key_xmlhttprequest.open("GET",
- "key?index=" + (keyIndex++)
- + "&pressed=" + pressed
- + "&keysym=" + keysym);
- key_xmlhttprequest.send(null);
+ sendMessage("key:" + keysym + "," + pressed + ";");
}
this.pressKey = function(keysym) {
@@ -170,47 +157,63 @@ function VNCClient(display) {
);
- var sendingMouseEvents = 0;
- var mouseEventBuffer = "";
-
function sendMouseState(mouseState) {
+ // Build mask
+ var buttonMask = 0;
+ if (mouseState.getLeft()) buttonMask |= 1;
+ if (mouseState.getMiddle()) buttonMask |= 2;
+ if (mouseState.getRight()) buttonMask |= 4;
+ if (mouseState.getUp()) buttonMask |= 8;
+ if (mouseState.getDown()) buttonMask |= 16;
+
+ // Send message
+ sendMessage("mouse:" + mouseState.getX() + "," + mouseState.getY() + "," + buttonMask + ";");
+ }
+
+ var sendingMessages = 0;
+ var outputMessageBuffer = "";
+
+ function sendMessage(message) {
+
// Do not send requests if not connected
if (!isConnected())
return;
// Add event to queue, restart send loop if finished.
- if (mouseEventBuffer.length > 0) mouseEventBuffer += "&";
- mouseEventBuffer += "event=" + mouseState.toString();
- if (sendingMouseEvents == 0)
- sendPendingMouseEvents();
+ outputMessageBuffer += message;
+ if (sendingMessages == 0)
+ sendPendingMessages();
}
- function sendPendingMouseEvents() {
+ function sendPendingMessages() {
// Do not send requests if not connected
if (!isConnected())
return;
- if (mouseEventBuffer.length > 0) {
+ if (outputMessageBuffer.length > 0) {
- sendingMouseEvents = 1;
+ sendingMessages = 1;
- var mouse_xmlhttprequest = new XMLHttpRequest();
- mouse_xmlhttprequest.open("GET", "pointer?" + mouseEventBuffer);
- mouseEventBuffer = ""; // Clear buffer
+ var message_xmlhttprequest = new XMLHttpRequest();
+ message_xmlhttprequest.open("POST", "inbound");
+ message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ message_xmlhttprequest.setRequestHeader("Content-length", outputMessageBuffer.length);
// Once response received, send next queued event.
- mouse_xmlhttprequest.onreadystatechange = function() {
- if (mouse_xmlhttprequest.readyState == 4)
- sendPendingMouseEvents();
+ message_xmlhttprequest.onreadystatechange = function() {
+ if (message_xmlhttprequest.readyState == 4)
+ sendPendingMessages();
}
- mouse_xmlhttprequest.send(null);
+ message_xmlhttprequest.send(outputMessageBuffer);
+ outputMessageBuffer = ""; // Clear buffer
+
}
else
- sendingMouseEvents = 0;
+ sendingMessages = 0;
}
@@ -225,10 +228,7 @@ function VNCClient(display) {
if (!isConnected())
return;
- var clipboard_xmlhttprequest = new XMLHttpRequest();
- clipboard_xmlhttprequest.open("POST", "clipboard");
- clipboard_xmlhttprequest.send(data);
-
+ sendMessage("clipboard:" + escapeGuacamoleString(data) + ";");
}
@@ -387,6 +387,28 @@ function VNCClient(display) {
}
+ function escapeGuacamoleString(str) {
+
+ var escapedString = "";
+
+ for (var i=0; i