mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-10 07:01:21 +00:00
GUACAMOLE-1: Refactor org.glyptodon package/groupId to org.apache.
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.io.GuacamoleReader;
|
||||
import org.apache.guacamole.io.GuacamoleWriter;
|
||||
import org.apache.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;
|
||||
|
||||
/**
|
||||
* The unique identifier associated with this connection, as determined
|
||||
* by the "ready" instruction received from the Guacamole proxy.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Waits for the instruction having the given opcode, returning that
|
||||
* instruction once it has been read. If the instruction is never read,
|
||||
* an exception is thrown.
|
||||
*
|
||||
* @param reader The reader to read instructions from.
|
||||
* @param opcode The opcode of the instruction we are expecting.
|
||||
* @return The instruction having the given opcode.
|
||||
* @throws GuacamoleException If an error occurs while reading, or if
|
||||
* the expected instruction is not read.
|
||||
*/
|
||||
private GuacamoleInstruction expect(GuacamoleReader reader, String opcode)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Wait for an instruction
|
||||
GuacamoleInstruction instruction = reader.readInstruction();
|
||||
if (instruction == null)
|
||||
throw new GuacamoleServerException("End of stream while waiting for \"" + opcode + "\".");
|
||||
|
||||
// Ensure instruction has expected opcode
|
||||
if (!instruction.getOpcode().equals(opcode))
|
||||
throw new GuacamoleServerException("Expected \"" + opcode + "\" instruction but instead received \"" + instruction.getOpcode() + "\".");
|
||||
|
||||
return instruction;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
// Get protocol / connection ID
|
||||
String select_arg = config.getConnectionID();
|
||||
if (select_arg == null)
|
||||
select_arg = config.getProtocol();
|
||||
|
||||
// Send requested protocol or connection ID
|
||||
writer.writeInstruction(new GuacamoleInstruction("select", select_arg));
|
||||
|
||||
// Wait for server args
|
||||
GuacamoleInstruction args = expect(reader, "args");
|
||||
|
||||
// Build args list off provided names and config
|
||||
List<String> arg_names = args.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()),
|
||||
Integer.toString(info.getOptimalResolution())
|
||||
)
|
||||
);
|
||||
|
||||
// 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 supported image formats
|
||||
writer.writeInstruction(
|
||||
new GuacamoleInstruction(
|
||||
"image",
|
||||
info.getImageMimetypes().toArray(new String[0])
|
||||
));
|
||||
|
||||
// Send args
|
||||
writer.writeInstruction(new GuacamoleInstruction("connect", arg_values));
|
||||
|
||||
// Wait for ready, store ID
|
||||
GuacamoleInstruction ready = expect(reader, "ready");
|
||||
|
||||
List<String> ready_args = ready.getArgs();
|
||||
if (ready_args.isEmpty())
|
||||
throw new GuacamoleServerException("No connection ID received");
|
||||
|
||||
id = ready.getArgs().get(0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GuacamoleConfiguration used to configure this
|
||||
* ConfiguredGuacamoleSocket.
|
||||
*
|
||||
* @return The GuacamoleConfiguration used to configure this
|
||||
* ConfiguredGuacamoleSocket.
|
||||
*/
|
||||
public GuacamoleConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID associated with the Guacamole connection
|
||||
* negotiated by this ConfiguredGuacamoleSocket. The ID is provided by
|
||||
* the "ready" instruction returned by the Guacamole proxy.
|
||||
*
|
||||
* @return The ID of the negotiated Guacamole connection.
|
||||
*/
|
||||
public String getConnectionID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.io.GuacamoleReader;
|
||||
|
||||
/**
|
||||
* GuacamoleReader which applies a given GuacamoleFilter to observe or alter all
|
||||
* read instructions. Instructions may also be dropped or denied by the the
|
||||
* filter.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class FilteredGuacamoleReader implements GuacamoleReader {
|
||||
|
||||
/**
|
||||
* The wrapped GuacamoleReader.
|
||||
*/
|
||||
private final GuacamoleReader reader;
|
||||
|
||||
/**
|
||||
* The filter to apply when reading instructions.
|
||||
*/
|
||||
private final GuacamoleFilter filter;
|
||||
|
||||
/**
|
||||
* Wraps the given GuacamoleReader, applying the given filter to all read
|
||||
* instructions. Future reads will return only instructions which pass
|
||||
* the filter.
|
||||
*
|
||||
* @param reader The GuacamoleReader to wrap.
|
||||
* @param filter The filter which dictates which instructions are read, and
|
||||
* how.
|
||||
*/
|
||||
public FilteredGuacamoleReader(GuacamoleReader reader, GuacamoleFilter filter) {
|
||||
this.reader = reader;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available() throws GuacamoleException {
|
||||
return reader.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] read() throws GuacamoleException {
|
||||
|
||||
GuacamoleInstruction filteredInstruction = readInstruction();
|
||||
if (filteredInstruction == null)
|
||||
return null;
|
||||
|
||||
return filteredInstruction.toString().toCharArray();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleInstruction readInstruction() throws GuacamoleException {
|
||||
|
||||
GuacamoleInstruction filteredInstruction;
|
||||
|
||||
// Read and filter instructions until no instructions are dropped
|
||||
do {
|
||||
|
||||
// Read next instruction
|
||||
GuacamoleInstruction unfilteredInstruction = reader.readInstruction();
|
||||
if (unfilteredInstruction == null)
|
||||
return null;
|
||||
|
||||
// Apply filter
|
||||
filteredInstruction = filter.filter(unfilteredInstruction);
|
||||
|
||||
} while (filteredInstruction == null);
|
||||
|
||||
return filteredInstruction;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.io.GuacamoleReader;
|
||||
import org.apache.guacamole.io.GuacamoleWriter;
|
||||
import org.apache.guacamole.net.GuacamoleSocket;
|
||||
|
||||
/**
|
||||
* Implementation of GuacamoleSocket which allows individual instructions to be
|
||||
* intercepted, overridden, etc.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class FilteredGuacamoleSocket implements GuacamoleSocket {
|
||||
|
||||
/**
|
||||
* Wrapped GuacamoleSocket.
|
||||
*/
|
||||
private final GuacamoleSocket socket;
|
||||
|
||||
/**
|
||||
* A reader for the wrapped GuacamoleSocket which may be filtered.
|
||||
*/
|
||||
private final GuacamoleReader reader;
|
||||
|
||||
/**
|
||||
* A writer for the wrapped GuacamoleSocket which may be filtered.
|
||||
*/
|
||||
private final GuacamoleWriter writer;
|
||||
|
||||
/**
|
||||
* Creates a new FilteredGuacamoleSocket which uses the given filters to
|
||||
* determine whether instructions read/written are allowed through,
|
||||
* modified, etc. If reads or writes should be unfiltered, simply specify
|
||||
* null rather than a particular filter.
|
||||
*
|
||||
* @param socket The GuacamoleSocket to wrap.
|
||||
* @param readFilter The GuacamoleFilter to apply to all read instructions,
|
||||
* if any.
|
||||
* @param writeFilter The GuacamoleFilter to apply to all written
|
||||
* instructions, if any.
|
||||
*/
|
||||
public FilteredGuacamoleSocket(GuacamoleSocket socket, GuacamoleFilter readFilter, GuacamoleFilter writeFilter) {
|
||||
this.socket = socket;
|
||||
|
||||
// Apply filter to reader
|
||||
if (readFilter != null)
|
||||
reader = new FilteredGuacamoleReader(socket.getReader(), readFilter);
|
||||
else
|
||||
reader = socket.getReader();
|
||||
|
||||
// Apply filter to writer
|
||||
if (writeFilter != null)
|
||||
writer = new FilteredGuacamoleWriter(socket.getWriter(), writeFilter);
|
||||
else
|
||||
writer = socket.getWriter();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleReader getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws GuacamoleException {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return socket.isOpen();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.io.GuacamoleWriter;
|
||||
|
||||
/**
|
||||
* GuacamoleWriter which applies a given GuacamoleFilter to observe or alter
|
||||
* all written instructions. Instructions may also be dropped or denied by
|
||||
* the filter.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class FilteredGuacamoleWriter implements GuacamoleWriter {
|
||||
|
||||
/**
|
||||
* The wrapped GuacamoleWriter.
|
||||
*/
|
||||
private final GuacamoleWriter writer;
|
||||
|
||||
/**
|
||||
* The filter to apply when writing instructions.
|
||||
*/
|
||||
private final GuacamoleFilter filter;
|
||||
|
||||
/**
|
||||
* Parser for reading instructions prior to writing, such that they can be
|
||||
* passed on to the filter.
|
||||
*/
|
||||
private final GuacamoleParser parser = new GuacamoleParser();
|
||||
|
||||
/**
|
||||
* Wraps the given GuacamoleWriter, applying the given filter to all written
|
||||
* instructions. Future writes will only write instructions which pass
|
||||
* the filter.
|
||||
*
|
||||
* @param writer The GuacamoleWriter to wrap.
|
||||
* @param filter The filter which dictates which instructions are written,
|
||||
* and how.
|
||||
*/
|
||||
public FilteredGuacamoleWriter(GuacamoleWriter writer, GuacamoleFilter filter) {
|
||||
this.writer = writer;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] chunk, int offset, int length) throws GuacamoleException {
|
||||
|
||||
// Write all data in chunk
|
||||
while (length > 0) {
|
||||
|
||||
// Pass as much data through the parser as possible
|
||||
int parsed;
|
||||
while ((parsed = parser.append(chunk, offset, length)) != 0) {
|
||||
offset += parsed;
|
||||
length -= parsed;
|
||||
}
|
||||
|
||||
// If no instruction is available, it must be incomplete
|
||||
if (!parser.hasNext())
|
||||
throw new GuacamoleServerException("Filtered write() contained an incomplete instruction.");
|
||||
|
||||
// Write single instruction through filter
|
||||
writeInstruction(parser.next());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] chunk) throws GuacamoleException {
|
||||
write(chunk, 0, chunk.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInstruction(GuacamoleInstruction instruction) throws GuacamoleException {
|
||||
|
||||
// Write instruction only if not dropped
|
||||
GuacamoleInstruction filteredInstruction = filter.filter(instruction);
|
||||
if (filteredInstruction != null)
|
||||
writer.writeInstruction(filteredInstruction);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
|
||||
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 resolution of the optimal dimensions given, in DPI.
|
||||
*/
|
||||
private int optimalResolution = 96;
|
||||
|
||||
/**
|
||||
* The list of audio mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> audioMimetypes = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* The list of video mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> videoMimetypes = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* The list of image mimetypes reported by the client to be supported.
|
||||
*/
|
||||
private final List<String> imageMimetypes = 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 resolution of the screen if the optimal width and height are
|
||||
* used, in DPI.
|
||||
*
|
||||
* @return The optimal screen resolution.
|
||||
*/
|
||||
public int getOptimalResolution() {
|
||||
return optimalResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resolution of the screen if the optimal width and height are
|
||||
* used, in DPI.
|
||||
*
|
||||
* @param optimalResolution The optimal screen resolution in DPI.
|
||||
*/
|
||||
public void setOptimalResolution(int optimalResolution) {
|
||||
this.optimalResolution = optimalResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of image mimetypes supported by the client. To add or
|
||||
* removed supported mimetypes, the list returned by this function can be
|
||||
* modified.
|
||||
*
|
||||
* @return
|
||||
* The set of image mimetypes supported by the client.
|
||||
*/
|
||||
public List<String> getImageMimetypes() {
|
||||
return imageMimetypes;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
|
||||
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 ID of the connection being joined. If this value is present,
|
||||
* the protocol need not be specified.
|
||||
*/
|
||||
private String connectionID;
|
||||
|
||||
/**
|
||||
* The name of the protocol associated with this configuration.
|
||||
*/
|
||||
private String protocol;
|
||||
|
||||
/**
|
||||
* Map of all associated parameter values, indexed by parameter name.
|
||||
*/
|
||||
private final Map<String, String> parameters = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Creates a new, blank GuacamoleConfiguration with its protocol, connection
|
||||
* ID, and parameters unset.
|
||||
*/
|
||||
public GuacamoleConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the given GuacamoleConfiguration, creating a new, indepedent
|
||||
* GuacamoleConfiguration containing the same protocol, connection ID,
|
||||
* and parameter values, if any.
|
||||
*
|
||||
* @param config The GuacamoleConfiguration to copy.
|
||||
*/
|
||||
public GuacamoleConfiguration(GuacamoleConfiguration config) {
|
||||
|
||||
// Copy protocol and connection ID
|
||||
protocol = config.getProtocol();
|
||||
connectionID = config.getConnectionID();
|
||||
|
||||
// Copy parameter values
|
||||
for (String name : config.getParameterNames())
|
||||
parameters.put(name, config.getParameter(name));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the connection being joined, if any. If no connection
|
||||
* is being joined, this returns null, and the protocol must be set.
|
||||
*
|
||||
* @return The ID of the connection being joined, or null if no connection
|
||||
* is being joined.
|
||||
*/
|
||||
public String getConnectionID() {
|
||||
return connectionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID of the connection being joined, if any. If no connection
|
||||
* is being joined, this value must be omitted, and the protocol must be
|
||||
* set instead.
|
||||
*
|
||||
* @param connectionID The ID of the connection being joined.
|
||||
*/
|
||||
public void setConnectionID(String connectionID) {
|
||||
this.connectionID = connectionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map which contains parameter name/value pairs as key/value
|
||||
* pairs. Changes to this map will affect the parameters stored within
|
||||
* this configuration.
|
||||
*
|
||||
* @return
|
||||
* A map which contains all parameter name/value pairs as key/value
|
||||
* pairs.
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all current parameters with the parameters defined within the
|
||||
* given map. Key/value pairs within the map represent parameter name/value
|
||||
* pairs.
|
||||
*
|
||||
* @param parameters
|
||||
* A map which contains all parameter name/value pairs as key/value
|
||||
* pairs.
|
||||
*/
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters.clear();
|
||||
this.parameters.putAll(parameters);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* Interface which provides for the filtering of individual instructions. Each
|
||||
* filtered instruction may be allowed through untouched, modified, replaced,
|
||||
* dropped, or explicitly denied.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface GuacamoleFilter {
|
||||
|
||||
/**
|
||||
* Applies the filter to the given instruction, returning the original
|
||||
* instruction, a modified version of the original, or null, depending
|
||||
* on the implementation.
|
||||
*
|
||||
* @param instruction The instruction to filter.
|
||||
* @return The original instruction, if the instruction is to be allowed,
|
||||
* a modified version of the instruction, if the instruction is
|
||||
* to be overridden, or null, if the instruction is to be dropped.
|
||||
* @throws GuacamoleException If an error occurs filtering the instruction,
|
||||
* or if the instruction must be explicitly
|
||||
* denied.
|
||||
*/
|
||||
public GuacamoleInstruction filter(GuacamoleInstruction instruction) throws GuacamoleException;
|
||||
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleInstruction having the given Operation and
|
||||
* list of arguments values. The list given will be used to back the
|
||||
* internal list of arguments and the list returned by getArgs().
|
||||
*
|
||||
* @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, List<String> args) {
|
||||
this.opcode = opcode;
|
||||
this.args = Collections.unmodifiableList(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();
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
|
||||
/**
|
||||
* Parser for the Guacamole protocol. Arbitrary instruction data is appended,
|
||||
* and instructions are returned as a result. Invalid instructions result in
|
||||
* exceptions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class GuacamoleParser implements Iterator<GuacamoleInstruction> {
|
||||
|
||||
/**
|
||||
* The maximum number of characters per instruction.
|
||||
*/
|
||||
public static final int INSTRUCTION_MAX_LENGTH = 8192;
|
||||
|
||||
/**
|
||||
* The maximum number of digits to allow per length prefix.
|
||||
*/
|
||||
public static final int INSTRUCTION_MAX_DIGITS = 5;
|
||||
|
||||
/**
|
||||
* The maximum number of elements per instruction, including the opcode.
|
||||
*/
|
||||
public static final int INSTRUCTION_MAX_ELEMENTS = 64;
|
||||
|
||||
/**
|
||||
* All possible states of the instruction parser.
|
||||
*/
|
||||
private enum State {
|
||||
|
||||
/**
|
||||
* The parser is currently waiting for data to complete the length prefix
|
||||
* of the current element of the instruction.
|
||||
*/
|
||||
PARSING_LENGTH,
|
||||
|
||||
/**
|
||||
* The parser has finished reading the length prefix and is currently
|
||||
* waiting for data to complete the content of the instruction.
|
||||
*/
|
||||
PARSING_CONTENT,
|
||||
|
||||
/**
|
||||
* The instruction has been fully parsed.
|
||||
*/
|
||||
COMPLETE,
|
||||
|
||||
/**
|
||||
* The instruction cannot be parsed because of a protocol error.
|
||||
*/
|
||||
ERROR
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The latest parsed instruction, if any.
|
||||
*/
|
||||
private GuacamoleInstruction parsedInstruction;
|
||||
|
||||
/**
|
||||
* The parse state of the instruction.
|
||||
*/
|
||||
private State state = State.PARSING_LENGTH;
|
||||
|
||||
/**
|
||||
* The length of the current element, if known.
|
||||
*/
|
||||
private int elementLength = 0;
|
||||
|
||||
/**
|
||||
* The number of elements currently parsed.
|
||||
*/
|
||||
private int elementCount = 0;
|
||||
|
||||
/**
|
||||
* All currently parsed elements.
|
||||
*/
|
||||
private final String elements[] = new String[INSTRUCTION_MAX_ELEMENTS];
|
||||
|
||||
/**
|
||||
* Appends data from the given buffer to the current instruction.
|
||||
*
|
||||
* @param chunk The buffer containing the data to append.
|
||||
* @param offset The offset within the buffer where the data begins.
|
||||
* @param length The length of the data to append.
|
||||
* @return The number of characters appended, or 0 if complete instructions
|
||||
* have already been parsed and must be read via next() before
|
||||
* more data can be appended.
|
||||
* @throws GuacamoleException If an error occurs while parsing the new data.
|
||||
*/
|
||||
public int append(char chunk[], int offset, int length) throws GuacamoleException {
|
||||
|
||||
int charsParsed = 0;
|
||||
|
||||
// Do not exceed maximum number of elements
|
||||
if (elementCount == INSTRUCTION_MAX_ELEMENTS && state != State.COMPLETE) {
|
||||
state = State.ERROR;
|
||||
throw new GuacamoleServerException("Instruction contains too many elements.");
|
||||
}
|
||||
|
||||
// Parse element length
|
||||
if (state == State.PARSING_LENGTH) {
|
||||
|
||||
int parsedLength = elementLength;
|
||||
while (charsParsed < length) {
|
||||
|
||||
// Pull next character
|
||||
char c = chunk[offset + charsParsed++];
|
||||
|
||||
// If digit, add to length
|
||||
if (c >= '0' && c <= '9')
|
||||
parsedLength = parsedLength*10 + c - '0';
|
||||
|
||||
// If period, switch to parsing content
|
||||
else if (c == '.') {
|
||||
state = State.PARSING_CONTENT;
|
||||
break;
|
||||
}
|
||||
|
||||
// If not digit, parse error
|
||||
else {
|
||||
state = State.ERROR;
|
||||
throw new GuacamoleServerException("Non-numeric character in element length.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If too long, parse error
|
||||
if (parsedLength > INSTRUCTION_MAX_LENGTH) {
|
||||
state = State.ERROR;
|
||||
throw new GuacamoleServerException("Instruction exceeds maximum length.");
|
||||
}
|
||||
|
||||
// Save length
|
||||
elementLength = parsedLength;
|
||||
|
||||
} // end parse length
|
||||
|
||||
// Parse element content, if available
|
||||
if (state == State.PARSING_CONTENT && charsParsed + elementLength + 1 <= length) {
|
||||
|
||||
// Read element
|
||||
String element = new String(chunk, offset + charsParsed, elementLength);
|
||||
charsParsed += elementLength;
|
||||
elementLength = 0;
|
||||
|
||||
// Read terminator char following element
|
||||
char terminator = chunk[offset + charsParsed++];
|
||||
|
||||
// Add element to currently parsed elements
|
||||
elements[elementCount++] = element;
|
||||
|
||||
// If semicolon, store end-of-instruction
|
||||
if (terminator == ';') {
|
||||
state = State.COMPLETE;
|
||||
parsedInstruction = new GuacamoleInstruction(elements[0],
|
||||
Arrays.asList(elements).subList(1, elementCount));
|
||||
}
|
||||
|
||||
// If comma, move on to next element
|
||||
else if (terminator == ',')
|
||||
state = State.PARSING_LENGTH;
|
||||
|
||||
// Otherwise, parse error
|
||||
else {
|
||||
state = State.ERROR;
|
||||
throw new GuacamoleServerException("Element terminator of instruction was not ';' nor ','");
|
||||
}
|
||||
|
||||
} // end parse content
|
||||
|
||||
return charsParsed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends data from the given buffer to the current instruction.
|
||||
*
|
||||
* @param chunk The data to append.
|
||||
* @return The number of characters appended, or 0 if complete instructions
|
||||
* have already been parsed and must be read via next() before
|
||||
* more data can be appended.
|
||||
* @throws GuacamoleException If an error occurs while parsing the new data.
|
||||
*/
|
||||
public int append(char chunk[]) throws GuacamoleException {
|
||||
return append(chunk, 0, chunk.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return state == State.COMPLETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleInstruction next() {
|
||||
|
||||
// No instruction to return if not yet complete
|
||||
if (state != State.COMPLETE)
|
||||
return null;
|
||||
|
||||
// Reset for next instruction.
|
||||
state = State.PARSING_LENGTH;
|
||||
elementCount = 0;
|
||||
elementLength = 0;
|
||||
|
||||
return parsedInstruction;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("GuacamoleParser does not support remove().");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.protocol;
|
||||
|
||||
/**
|
||||
* All possible statuses returned by various Guacamole instructions, each having
|
||||
* a corresponding code.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public enum GuacamoleStatus {
|
||||
|
||||
/**
|
||||
* The operation succeeded.
|
||||
*/
|
||||
SUCCESS(200, 1000, 0x0000),
|
||||
|
||||
/**
|
||||
* The requested operation is unsupported.
|
||||
*/
|
||||
UNSUPPORTED(501, 1011, 0x0100),
|
||||
|
||||
/**
|
||||
* The operation could not be performed due to an internal failure.
|
||||
*/
|
||||
SERVER_ERROR(500, 1011, 0x0200),
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the server is busy.
|
||||
*/
|
||||
SERVER_BUSY(503, 1008, 0x0201),
|
||||
|
||||
/**
|
||||
* The operation could not be performed because the upstream server is not
|
||||
* responding.
|
||||
*/
|
||||
UPSTREAM_TIMEOUT(504, 1011, 0x0202),
|
||||
|
||||
/**
|
||||
* The operation was unsuccessful due to an error or otherwise unexpected
|
||||
* condition of the upstream server.
|
||||
*/
|
||||
UPSTREAM_ERROR(502, 1011, 0x0203),
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the requested resource does not
|
||||
* exist.
|
||||
*/
|
||||
RESOURCE_NOT_FOUND(404, 1002, 0x0204),
|
||||
|
||||
/**
|
||||
* The operation could not be performed as the requested resource is already
|
||||
* in use.
|
||||
*/
|
||||
RESOURCE_CONFLICT(409, 1008, 0x0205),
|
||||
|
||||
/**
|
||||
* The operation could not be performed because bad parameters were given.
|
||||
*/
|
||||
CLIENT_BAD_REQUEST(400, 1002, 0x0300),
|
||||
|
||||
/**
|
||||
* Permission was denied to perform the operation, as the user is not yet
|
||||
* authorized (not yet logged in, for example). As HTTP 401 has implications
|
||||
* for HTTP-specific authorization schemes, this status continues to map to
|
||||
* HTTP 403 ("Forbidden"). To do otherwise would risk unintended effects.
|
||||
*/
|
||||
CLIENT_UNAUTHORIZED(403, 1008, 0x0301),
|
||||
|
||||
/**
|
||||
* Permission was denied to perform the operation, and this operation will
|
||||
* not be granted even if the user is authorized.
|
||||
*/
|
||||
CLIENT_FORBIDDEN(403, 1008, 0x0303),
|
||||
|
||||
/**
|
||||
* The client took too long to respond.
|
||||
*/
|
||||
CLIENT_TIMEOUT(408, 1002, 0x0308),
|
||||
|
||||
/**
|
||||
* The client sent too much data.
|
||||
*/
|
||||
CLIENT_OVERRUN(413, 1009, 0x030D),
|
||||
|
||||
/**
|
||||
* The client sent data of an unsupported or unexpected type.
|
||||
*/
|
||||
CLIENT_BAD_TYPE(415, 1003, 0x030F),
|
||||
|
||||
/**
|
||||
* The operation failed because the current client is already using too
|
||||
* many resources.
|
||||
*/
|
||||
CLIENT_TOO_MANY(429, 1008, 0x031D);
|
||||
|
||||
/**
|
||||
* The most applicable HTTP error code.
|
||||
*/
|
||||
private final int http_code;
|
||||
|
||||
/**
|
||||
* The most applicable WebSocket error code.
|
||||
*/
|
||||
private final int websocket_code;
|
||||
|
||||
/**
|
||||
* The Guacamole protocol status code.
|
||||
*/
|
||||
private final int guac_code;
|
||||
|
||||
/**
|
||||
* Initializes a GuacamoleStatusCode with the given HTTP and Guacamole
|
||||
* status/error code values.
|
||||
*
|
||||
* @param http_code The most applicable HTTP error code.
|
||||
* @param websocket_code The most applicable WebSocket error code.
|
||||
* @param guac_code The Guacamole protocol status code.
|
||||
*/
|
||||
private GuacamoleStatus(int http_code, int websocket_code, int guac_code) {
|
||||
this.http_code = http_code;
|
||||
this.websocket_code = websocket_code;
|
||||
this.guac_code = guac_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most applicable HTTP error code.
|
||||
*
|
||||
* @return The most applicable HTTP error code.
|
||||
*/
|
||||
public int getHttpStatusCode() {
|
||||
return http_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most applicable HTTP error code.
|
||||
*
|
||||
* @return The most applicable HTTP error code.
|
||||
*/
|
||||
public int getWebSocketCode() {
|
||||
return websocket_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Guacamole protocol status code.
|
||||
*
|
||||
* @return The corresponding Guacamole protocol status code.
|
||||
*/
|
||||
public int getGuacamoleStatusCode() {
|
||||
return guac_code;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes relating directly to the Guacamole protocol.
|
||||
*/
|
||||
package org.apache.guacamole.protocol;
|
||||
|
Reference in New Issue
Block a user