Remove central guac-dev repo reference. Refactor net.sourceforge.guacamole to org.glyptodon.guacamole. Extensions are remaining with their classes in net.sourceforge.guacamole for compatibility's sake until we have a better system for extensions.

This commit is contained in:
Michael Jumper
2013-08-25 13:39:00 -07:00
parent 4352e6d444
commit 5912ea402d
165 changed files with 652 additions and 710 deletions

View File

@@ -0,0 +1,79 @@
package org.glyptodon.guacamole;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A generic exception thrown when part of the Guacamole API encounters
* an error in the client's request. Such an error, if correctable, usually
* requires correction on the client side, not the server.
*
* @author Michael Jumper
*/
public class GuacamoleClientException extends GuacamoleException {
/**
* Creates a new GuacamoleException with the given message and cause.
*
* @param message A human readable description of the exception that
* occurred.
* @param cause The cause of this exception.
*/
public GuacamoleClientException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new GuacamoleException with the given message.
*
* @param message A human readable description of the exception that
* occurred.
*/
public GuacamoleClientException(String message) {
super(message);
}
/**
* Creates a new GuacamoleException with the given cause.
*
* @param cause The cause of this exception.
*/
public GuacamoleClientException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,78 @@
package org.glyptodon.guacamole;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A generic exception thrown when parts of the Guacamole API encounter
* errors.
*
* @author Michael Jumper
*/
public class GuacamoleException extends Exception {
/**
* Creates a new GuacamoleException with the given message and cause.
*
* @param message A human readable description of the exception that
* occurred.
* @param cause The cause of this exception.
*/
public GuacamoleException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new GuacamoleException with the given message.
*
* @param message A human readable description of the exception that
* occurred.
*/
public GuacamoleException(String message) {
super(message);
}
/**
* Creates a new GuacamoleException with the given cause.
*
* @param cause The cause of this exception.
*/
public GuacamoleException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,79 @@
package org.glyptodon.guacamole;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A generic exception thrown when part of the Guacamole API fails to find
* a requested resource, such as a configuration or tunnel.
*
* @author Michael Jumper
*/
public class GuacamoleResourceNotFoundException extends GuacamoleClientException {
/**
* Creates a new GuacamoleResourceNotFoundException with the given message
* and cause.
*
* @param message A human readable description of the exception that
* occurred.
* @param cause The cause of this exception.
*/
public GuacamoleResourceNotFoundException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new GuacamoleResourceNotFoundException with the given message.
*
* @param message A human readable description of the exception that
* occurred.
*/
public GuacamoleResourceNotFoundException(String message) {
super(message);
}
/**
* Creates a new GuacamoleResourceNotFoundException with the given cause.
*
* @param cause The cause of this exception.
*/
public GuacamoleResourceNotFoundException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,78 @@
package org.glyptodon.guacamole;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A security-related exception thrown when parts of the Guacamole API is
* denying access to a resource.
*
* @author Michael Jumper
*/
public class GuacamoleSecurityException extends GuacamoleClientException {
/**
* Creates a new GuacamoleSecurityException with the given message and cause.
*
* @param message A human readable description of the exception that
* occurred.
* @param cause The cause of this exception.
*/
public GuacamoleSecurityException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new GuacamoleSecurityException with the given message.
*
* @param message A human readable description of the exception that
* occurred.
*/
public GuacamoleSecurityException(String message) {
super(message);
}
/**
* Creates a new GuacamoleSecurityException with the given cause.
*
* @param cause The cause of this exception.
*/
public GuacamoleSecurityException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,79 @@
package org.glyptodon.guacamole;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* A generic exception thrown when part of the Guacamole API encounters
* an unexpected, internal error. An internal error, if correctable, would
* require correction on the server side, not the client.
*
* @author Michael Jumper
*/
public class GuacamoleServerException extends GuacamoleException {
/**
* Creates a new GuacamoleException with the given message and cause.
*
* @param message A human readable description of the exception that
* occurred.
* @param cause The cause of this exception.
*/
public GuacamoleServerException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a new GuacamoleException with the given message.
*
* @param message A human readable description of the exception that
* occurred.
*/
public GuacamoleServerException(String message) {
super(message);
}
/**
* Creates a new GuacamoleException with the given cause.
*
* @param cause The cause of this exception.
*/
public GuacamoleServerException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,89 @@
package org.glyptodon.guacamole.io;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
/**
* Provides abstract and raw character read access to a stream of Guacamole
* instructions.
*
* @author Michael Jumper
*/
public interface GuacamoleReader {
/**
* Returns whether instruction data is available for reading. Note that
* this does not guarantee an entire instruction is available. If a full
* instruction is not available, this function can return true, and a call
* to read() will still block.
*
* @return true if instruction data is available for reading, false
* otherwise.
* @throws GuacamoleException If an error occurs while checking for
* available data.
*/
public boolean available() throws GuacamoleException;
/**
* Reads at least one complete Guacamole instruction, returning a buffer
* containing one or more complete Guacamole instructions and no
* incomplete Guacamole instructions. This function will block until at
* least one complete instruction is available.
*
* @return A buffer containing at least one complete Guacamole instruction,
* or null if no more instructions are available for reading.
* @throws GuacamoleException If an error occurs while reading from the
* stream.
*/
public char[] read() throws GuacamoleException;
/**
* Reads exactly one complete Guacamole instruction and returns the fully
* parsed instruction.
*
* @return The next complete instruction from the stream, fully parsed, or
* null if no more instructions are available for reading.
* @throws GuacamoleException If an error occurs while reading from the
* stream, or if the instruction cannot be
* parsed.
*/
public GuacamoleInstruction readInstruction() throws GuacamoleException;
}

View File

@@ -0,0 +1,85 @@
package org.glyptodon.guacamole.io;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
/**
* Provides abstract and raw character write access to a stream of Guacamole
* instructions.
*
* @author Michael Jumper
*/
public interface GuacamoleWriter {
/**
* Writes a portion of the given array of characters to the Guacamole
* instruction stream. The portion must contain only complete Guacamole
* instructions.
*
* @param chunk An array of characters containing Guacamole instructions.
* @param off The start offset of the portion of the array to write.
* @param len The length of the portion of the array to write.
* @throws GuacamoleException If an error occurred while writing the
* portion of the array specified.
*/
public void write(char[] chunk, int off, int len) throws GuacamoleException;
/**
* Writes the entire given array of characters to the Guacamole instruction
* stream. The array must consist only of complete Guacamole instructions.
*
* @param chunk An array of characters consisting only of complete
* Guacamole instructions.
* @throws GuacamoleException If an error occurred while writing the
* the specified array.
*/
public void write(char[] chunk) throws GuacamoleException;
/**
* Writes the given fully parsed instruction to the Guacamole instruction
* stream.
*
* @param instruction The Guacamole instruction to write.
* @throws GuacamoleException If an error occurred while writing the
* instruction.
*/
public void writeInstruction(GuacamoleInstruction instruction) throws GuacamoleException;
}

View File

@@ -0,0 +1,276 @@
package org.glyptodon.guacamole.io;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.io.IOException;
import java.io.Reader;
import java.util.Deque;
import java.util.LinkedList;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
/**
* A GuacamoleReader which wraps a standard Java Reader, using that Reader as
* the Guacamole instruction stream.
*
* @author Michael Jumper
*/
public class ReaderGuacamoleReader implements GuacamoleReader {
/**
* Wrapped Reader to be used for all input.
*/
private Reader input;
/**
* Creates a new ReaderGuacamoleReader which will use the given Reader as
* the Guacamole instruction stream.
*
* @param input The Reader to use as the Guacamole instruction stream.
*/
public ReaderGuacamoleReader(Reader input) {
this.input = input;
}
/**
* The location within the received data buffer that parsing should begin
* when more data is read.
*/
private int parseStart;
/**
* The buffer holding all received, unparsed data.
*/
private char[] buffer = new char[20480];
/**
* The number of characters currently used within the data buffer. All
* other characters within the buffer are free space available for
* future reads.
*/
private int usedLength = 0;
@Override
public boolean available() throws GuacamoleException {
try {
return input.ready() || usedLength != 0;
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public char[] read() throws GuacamoleException {
try {
// While we're blocking, or input is available
for (;;) {
// Length of element
int elementLength = 0;
// Resume where we left off
int i = parseStart;
// Parse instruction in buffer
while (i < usedLength) {
// Read character
char readChar = buffer[i++];
// If digit, update length
if (readChar >= '0' && readChar <= '9')
elementLength = elementLength * 10 + readChar - '0';
// If not digit, check for end-of-length character
else if (readChar == '.') {
// Check if element present in buffer
if (i + elementLength < usedLength) {
// Get terminator
char terminator = buffer[i + elementLength];
// Move to character after terminator
i += elementLength + 1;
// Reset length
elementLength = 0;
// Continue here if necessary
parseStart = i;
// If terminator is semicolon, we have a full
// instruction.
if (terminator == ';') {
// Copy instruction data
char[] instruction = new char[i];
System.arraycopy(buffer, 0, instruction, 0, i);
// Update buffer
usedLength -= i;
parseStart = 0;
System.arraycopy(buffer, i, buffer, 0, usedLength);
return instruction;
}
// Handle invalid terminator characters
else if (terminator != ',')
throw new GuacamoleServerException("Element terminator of instruction was not ';' nor ','");
}
// Otherwise, read more data
else
break;
}
// Otherwise, parse error
else
throw new GuacamoleServerException("Non-numeric character in element length.");
}
// If past threshold, resize buffer before reading
if (usedLength > buffer.length/2) {
char[] biggerBuffer = new char[buffer.length*2];
System.arraycopy(buffer, 0, biggerBuffer, 0, usedLength);
buffer = biggerBuffer;
}
// Attempt to fill buffer
int numRead = input.read(buffer, usedLength, buffer.length - usedLength);
if (numRead == -1)
return null;
// Update used length
usedLength += numRead;
} // End read loop
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public GuacamoleInstruction readInstruction() throws GuacamoleException {
// Get instruction
char[] instructionBuffer = read();
// If EOF, return EOF
if (instructionBuffer == null)
return null;
// Start of element
int elementStart = 0;
// Build list of elements
Deque<String> elements = new LinkedList<String>();
while (elementStart < instructionBuffer.length) {
// Find end of length
int lengthEnd = -1;
for (int i=elementStart; i<instructionBuffer.length; i++) {
if (instructionBuffer[i] == '.') {
lengthEnd = i;
break;
}
}
// read() is required to return a complete instruction. If it does
// not, this is a severe internal error.
if (lengthEnd == -1)
throw new GuacamoleServerException("Read returned incomplete instruction.");
// Parse length
int length = Integer.parseInt(new String(
instructionBuffer,
elementStart,
lengthEnd - elementStart
));
// Parse element from just after period
elementStart = lengthEnd + 1;
String element = new String(
instructionBuffer,
elementStart,
length
);
// Append element to list of elements
elements.addLast(element);
// Read terminator after element
elementStart += length;
char terminator = instructionBuffer[elementStart];
// Continue reading instructions after terminator
elementStart++;
// If we've reached the end of the instruction
if (terminator == ';')
break;
}
// Pull opcode off elements list
String opcode = elements.removeFirst();
// Create instruction
GuacamoleInstruction instruction = new GuacamoleInstruction(
opcode,
elements.toArray(new String[elements.size()])
);
// Return parsed instruction
return instruction;
}
}

View File

@@ -0,0 +1,90 @@
package org.glyptodon.guacamole.io;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.io.IOException;
import java.io.Writer;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.protocol.GuacamoleInstruction;
/**
* A GuacamoleWriter which wraps a standard Java Writer, using that Writer as
* the Guacamole instruction stream.
*
* @author Michael Jumper
*/
public class WriterGuacamoleWriter implements GuacamoleWriter {
/**
* Wrapped Writer to be used for all output.
*/
private Writer output;
/**
* Creates a new WriterGuacamoleWriter which will use the given Writer as
* the Guacamole instruction stream.
*
* @param output The Writer to use as the Guacamole instruction stream.
*/
public WriterGuacamoleWriter(Writer output) {
this.output = output;
}
@Override
public void write(char[] chunk, int off, int len) throws GuacamoleException {
try {
output.write(chunk, off, len);
output.flush();
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public void write(char[] chunk) throws GuacamoleException {
write(chunk, 0, chunk.length);
}
@Override
public void writeInstruction(GuacamoleInstruction instruction) throws GuacamoleException {
write(instruction.toString().toCharArray());
}
}

View File

@@ -0,0 +1,6 @@
/**
* All classes relating directly to data input or output.
*/
package org.glyptodon.guacamole.io;

View File

@@ -0,0 +1,87 @@
package org.glyptodon.guacamole.net;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.GuacamoleWriter;
/**
* Provides abstract socket-like access to a Guacamole connection.
*
* @author Michael Jumper
*/
public interface GuacamoleSocket {
/**
* Returns a GuacamoleReader which can be used to read from the
* Guacamole instruction stream associated with the connection
* represented by this GuacamoleSocket.
*
* @return A GuacamoleReader which can be used to read from the
* Guacamole instruction stream.
*/
public GuacamoleReader getReader();
/**
* Returns a GuacamoleWriter which can be used to write to the
* Guacamole instruction stream associated with the connection
* represented by this GuacamoleSocket.
*
* @return A GuacamoleWriter which can be used to write to the
* Guacamole instruction stream.
*/
public GuacamoleWriter getWriter();
/**
* Releases all resources in use by the connection represented by this
* GuacamoleSocket.
*
* @throws GuacamoleException If an error occurs while releasing resources.
*/
public void close() throws GuacamoleException;
/**
* Returns whether this GuacamoleSocket is open and can be used for reading
* and writing.
*
* @return true if this GuacamoleSocket is open, false otherwise.
*/
public boolean isOpen();
}

View File

@@ -0,0 +1,195 @@
package org.glyptodon.guacamole.net;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.GuacamoleWriter;
/**
* Provides a unique identifier and synchronized access to the GuacamoleReader
* and GuacamoleWriter associated with a GuacamoleSocket.
*
* @author Michael Jumper
*/
public class GuacamoleTunnel {
/**
* The UUID associated with this tunnel. Every tunnel must have a
* corresponding UUID such that tunnel read/write requests can be
* directed to the proper tunnel.
*/
private UUID uuid;
/**
* The GuacamoleSocket that tunnel should use for communication on
* behalf of the connecting user.
*/
private GuacamoleSocket socket;
/**
* Lock acquired when a read operation is in progress.
*/
private ReentrantLock readerLock;
/**
* Lock acquired when a write operation is in progress.
*/
private ReentrantLock writerLock;
/**
* Creates a new GuacamoleTunnel which synchronizes access to the
* Guacamole instruction stream associated with the given GuacamoleSocket.
*
* @param socket The GuacamoleSocket to provide synchronized access for.
*/
public GuacamoleTunnel(GuacamoleSocket socket) {
this.socket = socket;
uuid = UUID.randomUUID();
readerLock = new ReentrantLock();
writerLock = new ReentrantLock();
}
/**
* Acquires exclusive read access to the Guacamole instruction stream
* and returns a GuacamoleReader for reading from that stream.
*
* @return A GuacamoleReader for reading from the Guacamole instruction
* stream.
*/
public GuacamoleReader acquireReader() {
readerLock.lock();
return socket.getReader();
}
/**
* Relinquishes exclusive read access to the Guacamole instruction
* stream. This function should be called whenever a thread finishes using
* a GuacamoleTunnel's GuacamoleReader.
*/
public void releaseReader() {
readerLock.unlock();
}
/**
* Returns whether there are threads waiting for read access to the
* Guacamole instruction stream.
*
* @return true if threads are waiting for read access the Guacamole
* instruction stream, false otherwise.
*/
public boolean hasQueuedReaderThreads() {
return readerLock.hasQueuedThreads();
}
/**
* Acquires exclusive write access to the Guacamole instruction stream
* and returns a GuacamoleWriter for writing to that stream.
*
* @return A GuacamoleWriter for writing to the Guacamole instruction
* stream.
*/
public GuacamoleWriter acquireWriter() {
writerLock.lock();
return socket.getWriter();
}
/**
* Relinquishes exclusive write access to the Guacamole instruction
* stream. This function should be called whenever a thread finishes using
* a GuacamoleTunnel's GuacamoleWriter.
*/
public void releaseWriter() {
writerLock.unlock();
}
/**
* Returns whether there are threads waiting for write access to the
* Guacamole instruction stream.
*
* @return true if threads are waiting for write access the Guacamole
* instruction stream, false otherwise.
*/
public boolean hasQueuedWriterThreads() {
return writerLock.hasQueuedThreads();
}
/**
* Returns the unique identifier associated with this GuacamoleTunnel.
*
* @return The unique identifier associated with this GuacamoleTunnel.
*/
public UUID getUUID() {
return uuid;
}
/**
* Returns the GuacamoleSocket used by this GuacamoleTunnel for reading
* and writing.
*
* @return The GuacamoleSocket used by this GuacamoleTunnel.
*/
public GuacamoleSocket getSocket() {
return socket;
}
/**
* Release all resources allocated to this GuacamoleTunnel.
*
* @throws GuacamoleException if an error occurs while releasing
* resources.
*/
public void close() throws GuacamoleException {
socket.close();
}
/**
* Returns whether this GuacamoleTunnel is open, or has been closed.
*
* @return true if this GuacamoleTunnel is open, false if it is closed.
*/
public boolean isOpen() {
return socket.isOpen();
}
}

View File

@@ -0,0 +1,160 @@
package org.glyptodon.guacamole.net;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.ReaderGuacamoleReader;
import org.glyptodon.guacamole.io.WriterGuacamoleWriter;
import org.glyptodon.guacamole.io.GuacamoleWriter;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides abstract socket-like access to a Guacamole connection over a given
* hostname and port.
*
* @author Michael Jumper
*/
public class InetGuacamoleSocket implements GuacamoleSocket {
/**
* Logger for this class.
*/
private Logger logger = LoggerFactory.getLogger(InetGuacamoleSocket.class);
/**
* The GuacamoleReader this socket should read from.
*/
private GuacamoleReader reader;
/**
* The GuacamoleWriter this socket should write to.
*/
private GuacamoleWriter writer;
/**
* The number of milliseconds to wait for data on the TCP socket before
* timing out.
*/
private static final int SOCKET_TIMEOUT = 15000;
/**
* The TCP socket that the GuacamoleReader and GuacamoleWriter exposed
* by this class should affect.
*/
private Socket sock;
/**
* Creates a new InetGuacamoleSocket which reads and writes instructions
* to the Guacamole instruction stream of the Guacamole proxy server
* running at the given hostname and port.
*
* @param hostname The hostname of the Guacamole proxy server to connect to.
* @param port The port of the Guacamole proxy server to connect to.
* @throws GuacamoleException If an error occurs while connecting to the
* Guacamole proxy server.
*/
public InetGuacamoleSocket(String hostname, int port) throws GuacamoleException {
try {
logger.debug("Connecting to guacd at {}:{}.", hostname, port);
// Get address
SocketAddress address = new InetSocketAddress(
InetAddress.getByName(hostname),
port
);
// Connect with timeout
sock = new Socket();
sock.connect(address, SOCKET_TIMEOUT);
// Set read timeout
sock.setSoTimeout(SOCKET_TIMEOUT);
// On successful connect, retrieve I/O streams
reader = new ReaderGuacamoleReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
writer = new WriterGuacamoleWriter(new OutputStreamWriter(sock.getOutputStream(), "UTF-8"));
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public void close() throws GuacamoleException {
try {
logger.debug("Closing socket to guacd.");
sock.close();
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public GuacamoleReader getReader() {
return reader;
}
@Override
public GuacamoleWriter getWriter() {
return writer;
}
@Override
public boolean isOpen() {
return !sock.isClosed();
}
}

View File

@@ -0,0 +1,164 @@
package org.glyptodon.guacamole.net;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.GuacamoleWriter;
import org.glyptodon.guacamole.io.ReaderGuacamoleReader;
import org.glyptodon.guacamole.io.WriterGuacamoleWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides abstract socket-like access to a Guacamole connection over SSL to
* a given hostname and port.
*
* @author Michael Jumper
*/
public class SSLGuacamoleSocket implements GuacamoleSocket {
/**
* Logger for this class.
*/
private Logger logger = LoggerFactory.getLogger(SSLGuacamoleSocket.class);
/**
* The GuacamoleReader this socket should read from.
*/
private GuacamoleReader reader;
/**
* The GuacamoleWriter this socket should write to.
*/
private GuacamoleWriter writer;
/**
* The number of milliseconds to wait for data on the TCP socket before
* timing out.
*/
private static final int SOCKET_TIMEOUT = 15000;
/**
* The TCP socket that the GuacamoleReader and GuacamoleWriter exposed
* by this class should affect.
*/
private Socket sock;
/**
* Creates a new SSLGuacamoleSocket which reads and writes instructions
* to the Guacamole instruction stream of the Guacamole proxy server
* running at the given hostname and port using SSL.
*
* @param hostname The hostname of the Guacamole proxy server to connect to.
* @param port The port of the Guacamole proxy server to connect to.
* @throws GuacamoleException If an error occurs while connecting to the
* Guacamole proxy server.
*/
public SSLGuacamoleSocket(String hostname, int port) throws GuacamoleException {
// Get factory for SSL sockets
SocketFactory socket_factory = SSLSocketFactory.getDefault();
try {
logger.debug("Connecting to guacd at {}:{} via SSL/TLS.",
hostname, port);
// Get address
SocketAddress address = new InetSocketAddress(
InetAddress.getByName(hostname),
port
);
// Connect with timeout
sock = socket_factory.createSocket();
sock.connect(address, SOCKET_TIMEOUT);
// Set read timeout
sock.setSoTimeout(SOCKET_TIMEOUT);
// On successful connect, retrieve I/O streams
reader = new ReaderGuacamoleReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
writer = new WriterGuacamoleWriter(new OutputStreamWriter(sock.getOutputStream(), "UTF-8"));
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public void close() throws GuacamoleException {
try {
logger.debug("Closing socket to guacd.");
sock.close();
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
@Override
public GuacamoleReader getReader() {
return reader;
}
@Override
public GuacamoleWriter getWriter() {
return writer;
}
@Override
public boolean isOpen() {
return !sock.isClosed();
}
}

View File

@@ -0,0 +1,7 @@
/**
* Classes which apply to network-specific concepts, such as low-level sockets
* and tunnels.
*/
package org.glyptodon.guacamole.net;

View File

@@ -0,0 +1,8 @@
/**
* All classes which apply generally across the Guacamole web application
* and all other web applications which use the API provided by the
* Guacamole project.
*/
package org.glyptodon.guacamole;

View File

@@ -0,0 +1,206 @@
package org.glyptodon.guacamole.protocol;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.util.List;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.GuacamoleWriter;
import org.glyptodon.guacamole.net.GuacamoleSocket;
/**
* A GuacamoleSocket which pre-configures the connection based on a given
* GuacamoleConfiguration, completing the initial protocol handshake before
* accepting data for read or write.
*
* This is useful for forcing a connection to the Guacamole proxy server with
* a specific configuration while disallowing the client that will be using
* this GuacamoleSocket from manually controlling the initial protocol
* handshake.
*
* @author Michael Jumper
*/
public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
/**
* The wrapped socket.
*/
private GuacamoleSocket socket;
/**
* The configuration to use when performing the Guacamole protocol
* handshake.
*/
private GuacamoleConfiguration config;
/**
* Creates a new ConfiguredGuacamoleSocket which uses the given
* GuacamoleConfiguration to complete the initial protocol handshake over
* the given GuacamoleSocket. A default GuacamoleClientInformation object
* is used to provide basic client information.
*
* @param socket The GuacamoleSocket to wrap.
* @param config The GuacamoleConfiguration to use to complete the initial
* protocol handshake.
* @throws GuacamoleException If an error occurs while completing the
* initial protocol handshake.
*/
public ConfiguredGuacamoleSocket(GuacamoleSocket socket,
GuacamoleConfiguration config) throws GuacamoleException {
this(socket, config, new GuacamoleClientInformation());
}
/**
* Creates a new ConfiguredGuacamoleSocket which uses the given
* GuacamoleConfiguration and GuacamoleClientInformation to complete the
* initial protocol handshake over the given GuacamoleSocket.
*
* @param socket The GuacamoleSocket to wrap.
* @param config The GuacamoleConfiguration to use to complete the initial
* protocol handshake.
* @param info The GuacamoleClientInformation to use to complete the initial
* protocol handshake.
* @throws GuacamoleException If an error occurs while completing the
* initial protocol handshake.
*/
public ConfiguredGuacamoleSocket(GuacamoleSocket socket,
GuacamoleConfiguration config,
GuacamoleClientInformation info) throws GuacamoleException {
this.socket = socket;
this.config = config;
// Get reader and writer
GuacamoleReader reader = socket.getReader();
GuacamoleWriter writer = socket.getWriter();
// Send protocol
writer.writeInstruction(new GuacamoleInstruction("select", config.getProtocol()));
// Wait for server args
GuacamoleInstruction instruction;
do {
// Read instruction, fail if end-of-stream
instruction = reader.readInstruction();
if (instruction == null)
throw new GuacamoleServerException("End of stream during initial handshake.");
} while (!instruction.getOpcode().equals("args"));
// Build args list off provided names and config
List<String> arg_names = instruction.getArgs();
String[] arg_values = new String[arg_names.size()];
for (int i=0; i<arg_names.size(); i++) {
// Retrieve argument name
String arg_name = arg_names.get(i);
// Get defined value for name
String value = config.getParameter(arg_name);
// If value defined, set that value
if (value != null) arg_values[i] = value;
// Otherwise, leave value blank
else arg_values[i] = "";
}
// Send size
writer.writeInstruction(
new GuacamoleInstruction(
"size",
Integer.toString(info.getOptimalScreenWidth()),
Integer.toString(info.getOptimalScreenHeight())
)
);
// Send supported audio formats
writer.writeInstruction(
new GuacamoleInstruction(
"audio",
info.getAudioMimetypes().toArray(new String[0])
));
// Send supported video formats
writer.writeInstruction(
new GuacamoleInstruction(
"video",
info.getVideoMimetypes().toArray(new String[0])
));
// Send args
writer.writeInstruction(new GuacamoleInstruction("connect", arg_values));
}
/**
* Returns the GuacamoleConfiguration used to configure this
* ConfiguredGuacamoleSocket.
*
* @return The GuacamoleConfiguration used to configure this
* ConfiguredGuacamoleSocket.
*/
public GuacamoleConfiguration getConfiguration() {
return config;
}
@Override
public GuacamoleWriter getWriter() {
return socket.getWriter();
}
@Override
public GuacamoleReader getReader() {
return socket.getReader();
}
@Override
public void close() throws GuacamoleException {
socket.close();
}
@Override
public boolean isOpen() {
return socket.isOpen();
}
}

View File

@@ -0,0 +1,125 @@
package org.glyptodon.guacamole.protocol;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.util.ArrayList;
import java.util.List;
/**
* An abstract representation of Guacamole client information, including all
* information required by the Guacamole protocol during the preamble.
*
* @author Michael Jumper
*/
public class GuacamoleClientInformation {
/**
* The optimal screen width requested by the client, in pixels.
*/
private int optimalScreenWidth = 1024;
/**
* The optimal screen height requested by the client, in pixels.
*/
private int optimalScreenHeight = 768;
/**
* The list of audio mimetypes reported by the client to be supported.
*/
private List<String> audioMimetypes = new ArrayList<String>();
/**
* The list of audio mimetypes reported by the client to be supported.
*/
private List<String> videoMimetypes = new ArrayList<String>();
/**
* Returns the optimal screen width requested by the client, in pixels.
* @return The optimal screen width requested by the client, in pixels.
*/
public int getOptimalScreenWidth() {
return optimalScreenWidth;
}
/**
* Sets the client's optimal screen width.
* @param optimalScreenWidth The optimal screen width of the client.
*/
public void setOptimalScreenWidth(int optimalScreenWidth) {
this.optimalScreenWidth = optimalScreenWidth;
}
/**
* Returns the optimal screen height requested by the client, in pixels.
* @return The optimal screen height requested by the client, in pixels.
*/
public int getOptimalScreenHeight() {
return optimalScreenHeight;
}
/**
* Sets the client's optimal screen height.
* @param optimalScreenHeight The optimal screen height of the client.
*/
public void setOptimalScreenHeight(int optimalScreenHeight) {
this.optimalScreenHeight = optimalScreenHeight;
}
/**
* Returns the list of audio mimetypes supported by the client. To add or
* removed supported mimetypes, the list returned by this function can be
* modified.
*
* @return The set of audio mimetypes supported by the client.
*/
public List<String> getAudioMimetypes() {
return audioMimetypes;
}
/**
* Returns the list of video mimetypes supported by the client. To add or
* removed supported mimetypes, the list returned by this function can be
* modified.
*
* @return The set of video mimetypes supported by the client.
*/
public List<String> getVideoMimetypes() {
return videoMimetypes;
}
}

View File

@@ -0,0 +1,125 @@
package org.glyptodon.guacamole.protocol;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* All information necessary to complete the initial protocol handshake of a
* Guacamole session.
*
* @author Michael Jumper
*/
public class GuacamoleConfiguration implements Serializable {
/**
* Identifier unique to this version of GuacamoleConfiguration.
*/
private static final long serialVersionUID = 1L;
/**
* The name of the protocol associated with this configuration.
*/
private String protocol;
/**
* Map of all associated parameter values, indexed by parameter name.
*/
private Map<String, String> parameters = new HashMap<String, String>();
/**
* Returns the name of the protocol to be used.
* @return The name of the protocol to be used.
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the name of the protocol to be used.
* @param protocol The name of the protocol to be used.
*/
public void setProtocol(String protocol) {
this.protocol = protocol;
}
/**
* Returns the value set for the parameter with the given name, if any.
* @param name The name of the parameter to return the value for.
* @return The value of the parameter with the given name, or null if
* that parameter has not been set.
*/
public String getParameter(String name) {
return parameters.get(name);
}
/**
* Sets the value for the parameter with the given name.
*
* @param name The name of the parameter to set the value for.
* @param value The value to set for the parameter with the given name.
*/
public void setParameter(String name, String value) {
parameters.put(name, value);
}
/**
* Removes the value set for the parameter with the given name.
*
* @param name The name of the parameter to remove the value of.
*/
public void unsetParameter(String name) {
parameters.remove(name);
}
/**
* Returns a set of all currently defined parameter names. Each name
* corresponds to a parameter that has a value set on this
* GuacamoleConfiguration via setParameter().
*
* @return A set of all currently defined parameter names.
*/
public Set<String> getParameterNames() {
return Collections.unmodifiableSet(parameters.keySet());
}
}

View File

@@ -0,0 +1,127 @@
package org.glyptodon.guacamole.protocol;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* An abstract representation of a Guacamole instruction, as defined by the
* Guacamole protocol.
*
* @author Michael Jumper
*/
public class GuacamoleInstruction {
/**
* The opcode of this instruction.
*/
private String opcode;
/**
* All arguments of this instruction, in order.
*/
private List<String> args;
/**
* Creates a new GuacamoleInstruction having the given Operation and
* list of arguments values.
*
* @param opcode The opcode of the instruction to create.
* @param args The list of argument values to provide in the new
* instruction if any.
*/
public GuacamoleInstruction(String opcode, String... args) {
this.opcode = opcode;
this.args = Collections.unmodifiableList(Arrays.asList(args));
}
/**
* Returns the opcode associated with this GuacamoleInstruction.
* @return The opcode associated with this GuacamoleInstruction.
*/
public String getOpcode() {
return opcode;
}
/**
* Returns a List of all argument values specified for this
* GuacamoleInstruction. Note that the List returned is immutable.
* Attempts to modify the list will result in exceptions.
*
* @return A List of all argument values specified for this
* GuacamoleInstruction.
*/
public List<String> getArgs() {
return args;
}
/**
* Returns this GuacamoleInstruction in the form it would be sent over the
* Guacamole protocol.
*
* @return This GuacamoleInstruction in the form it would be sent over the
* Guacamole protocol.
*/
@Override
public String toString() {
StringBuilder buff = new StringBuilder();
// Write opcode
buff.append(opcode.length());
buff.append('.');
buff.append(opcode);
// Write argument values
for (String value : args) {
buff.append(',');
buff.append(value.length());
buff.append('.');
buff.append(value);
}
// Write terminator
buff.append(';');
return buff.toString();
}
}

View File

@@ -0,0 +1,6 @@
/**
* Classes relating directly to the Guacamole protocol.
*/
package org.glyptodon.guacamole.protocol;

View File

@@ -0,0 +1,452 @@
package org.glyptodon.guacamole.servlet;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.glyptodon.guacamole.GuacamoleClientException;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.GuacamoleServerException;
import org.glyptodon.guacamole.io.GuacamoleReader;
import org.glyptodon.guacamole.io.GuacamoleWriter;
import org.glyptodon.guacamole.net.GuacamoleTunnel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A HttpServlet implementing and abstracting the operations required by the
* HTTP implementation of the JavaScript Guacamole client's tunnel.
*
* @author Michael Jumper
*/
public abstract class GuacamoleHTTPTunnelServlet extends HttpServlet {
/**
* Logger for this class.
*/
private Logger logger = LoggerFactory.getLogger(GuacamoleHTTPTunnelServlet.class);
/**
* The prefix of the query string which denotes a tunnel read operation.
*/
private static final String READ_PREFIX = "read:";
/**
* The prefix of the query string which denotes a tunnel write operation.
*/
private static final String WRITE_PREFIX = "write:";
/**
* The length of the read prefix, in characters.
*/
private static final int READ_PREFIX_LENGTH = READ_PREFIX.length();
/**
* The length of the write prefix, in characters.
*/
private static final int WRITE_PREFIX_LENGTH = WRITE_PREFIX.length();
/**
* The length of every tunnel UUID, in characters.
*/
private static final int UUID_LENGTH = 36;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
handleTunnelRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
handleTunnelRequest(request, response);
}
/**
* Sends an error on the given HTTP response with the given integer error
* code.
*
* @param response The HTTP response to use to send the error.
* @param code The HTTP status code of the error.
* @throws ServletException If an error prevents sending of the error
* code.
*/
private void sendError(HttpServletResponse response, int code) throws ServletException {
try {
// If response not committed, send error code
if (!response.isCommitted())
response.sendError(code);
}
catch (IOException ioe) {
// If unable to send error at all due to I/O problems,
// rethrow as servlet exception
throw new ServletException(ioe);
}
}
/**
* Dispatches every HTTP GET and POST request to the appropriate handler
* function based on the query string.
*
* @param request The HttpServletRequest associated with the GET or POST
* request received.
* @param response The HttpServletResponse associated with the GET or POST
* request received.
* @throws ServletException If an error occurs while servicing the request.
*/
protected void handleTunnelRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
String query = request.getQueryString();
if (query == null)
throw new GuacamoleClientException("No query string provided.");
// If connect operation, call doConnect() and return tunnel UUID
// in response.
if (query.equals("connect")) {
GuacamoleTunnel tunnel = doConnect(request);
if (tunnel != null) {
// Get session
HttpSession httpSession = request.getSession(true);
GuacamoleSession session = new GuacamoleSession(httpSession);
// Attach tunnel to session
session.attachTunnel(tunnel);
logger.info("Connection from {} succeeded.", request.getRemoteAddr());
try {
// Ensure buggy browsers do not cache response
response.setHeader("Cache-Control", "no-cache");
// Send UUID to client
response.getWriter().print(tunnel.getUUID().toString());
}
catch (IOException e) {
throw new GuacamoleServerException(e);
}
}
// Failed to connect
else {
logger.info("Connection from {} failed.", request.getRemoteAddr());
throw new GuacamoleResourceNotFoundException("No tunnel created.");
}
}
// If read operation, call doRead() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
else if(query.startsWith(READ_PREFIX))
doRead(request, response, query.substring(
READ_PREFIX_LENGTH,
READ_PREFIX_LENGTH + UUID_LENGTH));
// If write operation, call doWrite() with tunnel UUID, ignoring any
// characters following the tunnel UUID.
else if(query.startsWith(WRITE_PREFIX))
doWrite(request, response, query.substring(
WRITE_PREFIX_LENGTH,
WRITE_PREFIX_LENGTH + UUID_LENGTH));
// Otherwise, invalid operation
else
throw new GuacamoleClientException("Invalid tunnel operation: " + query);
}
// Catch any thrown guacamole exception and attempt to pass within the
// HTTP response, logging each error appropriately.
catch (GuacamoleSecurityException e) {
logger.warn("Authorization failed.", e);
sendError(response, HttpServletResponse.SC_FORBIDDEN);
}
catch (GuacamoleResourceNotFoundException e) {
logger.debug("Resource not found.", e);
sendError(response, HttpServletResponse.SC_NOT_FOUND);
}
catch (GuacamoleClientException e) {
logger.warn("Error in client request.", e);
sendError(response, HttpServletResponse.SC_BAD_REQUEST);
}
catch (GuacamoleException e) {
logger.error("Server error in tunnel", e);
sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/**
* Called whenever the JavaScript Guacamole client makes a connection
* request. It it up to the implementor of this function to define what
* conditions must be met for a tunnel to be configured and returned as a
* result of this connection request (whether some sort of credentials must
* be specified, for example).
*
* @param request The HttpServletRequest associated with the connection
* request received. Any parameters specified along with
* the connection request can be read from this object.
* @return A newly constructed GuacamoleTunnel if successful,
* null otherwise.
* @throws GuacamoleException If an error occurs while constructing the
* GuacamoleTunnel, or if the conditions
* required for connection are not met.
*/
protected abstract GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException;
/**
* Called whenever the JavaScript Guacamole client makes a read request.
* This function should in general not be overridden, as it already
* contains a proper implementation of the read operation.
*
* @param request The HttpServletRequest associated with the read request
* received.
* @param response The HttpServletResponse associated with the write request
* received. Any data to be sent to the client in response
* to the write request should be written to the response
* body of this HttpServletResponse.
* @param tunnelUUID The UUID of the tunnel to read from, as specified in
* the write request. This tunnel must be attached to
* the Guacamole session.
* @throws GuacamoleException If an error occurs while handling the read
* request.
*/
protected void doRead(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {
HttpSession httpSession = request.getSession(false);
GuacamoleSession session = new GuacamoleSession(httpSession);
// Get tunnel, ensure tunnel exists
GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
if (tunnel == null)
throw new GuacamoleResourceNotFoundException("No such tunnel.");
// Ensure tunnel is open
if (!tunnel.isOpen())
throw new GuacamoleResourceNotFoundException("Tunnel is closed.");
// Obtain exclusive read access
GuacamoleReader reader = tunnel.acquireReader();
try {
// Note that although we are sending text, Webkit browsers will
// buffer 1024 bytes before starting a normal stream if we use
// anything but application/octet-stream.
response.setContentType("application/octet-stream");
response.setHeader("Cache-Control", "no-cache");
// Get writer for response
Writer out = new BufferedWriter(new OutputStreamWriter(
response.getOutputStream(), "UTF-8"));
// Stream data to response, ensuring output stream is closed
try {
// Detach tunnel and throw error if EOF (and we haven't sent any
// data yet.
char[] message = reader.read();
if (message == null)
throw new GuacamoleResourceNotFoundException("Tunnel reached end of stream.");
// For all messages, until another stream is ready (we send at least one message)
do {
// Get message output bytes
out.write(message, 0, message.length);
// Flush if we expect to wait
if (!reader.available()) {
out.flush();
response.flushBuffer();
}
// No more messages another stream can take over
if (tunnel.hasQueuedReaderThreads())
break;
} while (tunnel.isOpen() && (message = reader.read()) != null);
// Close tunnel immediately upon EOF
if (message == null)
tunnel.close();
// End-of-instructions marker
out.write("0.;");
out.flush();
response.flushBuffer();
}
// Always close output stream
finally {
out.close();
}
}
catch (GuacamoleException e) {
// Detach and close
session.detachTunnel(tunnel);
tunnel.close();
throw e;
}
catch (IOException e) {
// Log typically frequent I/O error if desired
logger.debug("Error writing to servlet output stream", e);
// Detach and close
session.detachTunnel(tunnel);
tunnel.close();
}
finally {
tunnel.releaseReader();
}
}
/**
* Called whenever the JavaScript Guacamole client makes a write request.
* This function should in general not be overridden, as it already
* contains a proper implementation of the write operation.
*
* @param request The HttpServletRequest associated with the write request
* received. Any data to be written will be specified within
* the body of this request.
* @param response The HttpServletResponse associated with the write request
* received.
* @param tunnelUUID The UUID of the tunnel to write to, as specified in
* the write request. This tunnel must be attached to
* the Guacamole session.
* @throws GuacamoleException If an error occurs while handling the write
* request.
*/
protected void doWrite(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {
HttpSession httpSession = request.getSession(false);
GuacamoleSession session = new GuacamoleSession(httpSession);
GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
if (tunnel == null)
throw new GuacamoleResourceNotFoundException("No such tunnel.");
// We still need to set the content type to avoid the default of
// text/html, as such a content type would cause some browsers to
// attempt to parse the result, even though the JavaScript client
// does not explicitly request such parsing.
response.setContentType("application/octet-stream");
response.setHeader("Cache-Control", "no-cache");
response.setContentLength(0);
// Send data
try {
// Get writer from tunnel
GuacamoleWriter writer = tunnel.acquireWriter();
// Get input reader for HTTP stream
Reader input = new InputStreamReader(
request.getInputStream(), "UTF-8");
// Transfer data from input stream to tunnel output, ensuring
// input is always closed
try {
// Buffer
int length;
char[] buffer = new char[8192];
// Transfer data using buffer
while (tunnel.isOpen() &&
(length = input.read(buffer, 0, buffer.length)) != -1)
writer.write(buffer, 0, length);
}
// Close input stream in all cases
finally {
input.close();
}
}
catch (IOException e) {
// Detach and close
session.detachTunnel(tunnel);
tunnel.close();
throw new GuacamoleServerException("I/O Error sending data to server: " + e.getMessage(), e);
}
finally {
tunnel.releaseWriter();
}
}
}
/**
* \example ExampleTunnelServlet.java
*
* A basic example demonstrating extending GuacamoleTunnelServlet and
* implementing doConnect() to configure the Guacamole connection as
* desired.
*/

View File

@@ -0,0 +1,125 @@
package org.glyptodon.guacamole.servlet;
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is guacamole-common.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpSession;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.GuacamoleSecurityException;
import org.glyptodon.guacamole.net.GuacamoleTunnel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides abstract access to the tunnels associated with a Guacamole session.
*
* @author Michael Jumper
*/
public class GuacamoleSession {
/**
* Logger for this class.
*/
private Logger logger = LoggerFactory.getLogger(GuacamoleSession.class);
/**
* Map of all currently attached tunnels, indexed by tunnel UUID.
*/
private ConcurrentMap<String, GuacamoleTunnel> tunnels;
/**
* Creates a new GuacamoleSession, storing and retrieving tunnels from the
* given HttpSession. Note that the true Guacamole session is tied to the
* HttpSession provided, thus creating a new GuacamoleSession does not
* create a new Guacamole session; it merely creates a new object for
* accessing the tunnels of an existing Guacamole session represented by
* the provided HttpSession.
*
* @param session The HttpSession to use as tunnel storage.
* @throws GuacamoleException If session is null.
*/
@SuppressWarnings("unchecked")
public GuacamoleSession(HttpSession session) throws GuacamoleException {
if (session == null)
throw new GuacamoleSecurityException("User has no session.");
synchronized (session) {
tunnels = (ConcurrentMap<String, GuacamoleTunnel>) session.getAttribute("GUAC_TUNNELS");
if (tunnels == null) {
tunnels = new ConcurrentHashMap<String, GuacamoleTunnel>();
session.setAttribute("GUAC_TUNNELS", tunnels);
}
}
}
/**
* Attaches the given tunnel to this GuacamoleSession.
* @param tunnel The tunnel to attach to this GucacamoleSession.
*/
public void attachTunnel(GuacamoleTunnel tunnel) {
tunnels.put(tunnel.getUUID().toString(), tunnel);
logger.debug("Attached tunnel {}.", tunnel.getUUID());
}
/**
* Detaches the given tunnel to this GuacamoleSession.
* @param tunnel The tunnel to detach to this GucacamoleSession.
*/
public void detachTunnel(GuacamoleTunnel tunnel) {
tunnels.remove(tunnel.getUUID().toString());
logger.debug("Detached tunnel {}.", tunnel.getUUID());
}
/**
* Returns the tunnel with the given UUID attached to this GuacamoleSession,
* if any.
*
* @param tunnelUUID The UUID of an attached tunnel.
* @return The tunnel corresponding to the given UUID, if attached, or null
* if no such tunnel is attached.
*/
public GuacamoleTunnel getTunnel(String tunnelUUID) {
return tunnels.get(tunnelUUID);
}
}

View File

@@ -0,0 +1,7 @@
/**
* Classes which build upon the Java Servlet API, providing an HTTP-based
* tunnel and session management.
*/
package org.glyptodon.guacamole.servlet;