| <?xml version="1.0" encoding="UTF-8"?> |
| <chapter xml:id="guacamole-common" xmlns="http://docbook.org/ns/docbook" |
| version="5.0" xml:lang="en" xmlns:xl="http://www.w3.org/1999/xlink" |
| xmlns:xi="http://www.w3.org/2001/XInclude"> |
| <title><package>guacamole-common</package></title> |
| <indexterm> |
| <primary>API</primary> |
| <secondary>Java</secondary> |
| </indexterm> |
| <indexterm> |
| <primary><package>guacamole-common</package></primary> |
| </indexterm> |
| <para>The Java API provided by the Guacamole project is called |
| guacamole-common. It provides a basic means of tunneling data between |
| the JavaScript client provided by guacamole-common-js and the native |
| proxy daemon, guacd. There are other classes provided as well which make |
| dealing with the Guacamole protocol and reading from |
| <filename>guacamole.properties</filename> easier, but in general, |
| the purpose of this library is to facilitate the creation of custom |
| tunnels between the JavaScript client and guacd.</para> |
| <section xml:id="java-http-tunnel"> |
| <title>HTTP tunnel</title> |
| <para>The Guacamole Java API implements the HTTP tunnel using a servlet |
| called <classname>GuacamoleHTTPTunnelServlet</classname>. This |
| servlet handles all requests coming to it over HTTP from the |
| JavaScript client, and translated them into connect, read, or write |
| requests, which each get dispatched to the |
| <methodname>doConnect()</methodname>, |
| <methodname>doRead()</methodname>, and |
| <methodname>doWrite()</methodname> functions accordingly.</para> |
| <para>Normally, you wouldn't touch the <methodname>doRead()</methodname> |
| and <methodname>doWrite()</methodname> functions, as these have |
| already been written to properly handle the requests of the |
| JavaScript tunnel, and if you feel the need to touch these |
| functions, you are probably better off writing your own tunnel |
| implementation, although such a thing is difficult to do in a |
| performant way.</para> |
| <para>When developing an application based on the Guacamole API, you |
| should use <classname>GuacamoleHTTPTunnelServlet</classname> by |
| extending it, implementing your own version of |
| <methodname>doConnect()</methodname>, which is the only abstract |
| function it defines. The tutorial later in this book demonstrating |
| how to write a Guacamole-based web application shows the basics of |
| doing this, but generally, <methodname>doConnect()</methodname> is |
| an excellent place for authentication or other validation, as it is |
| the responsibility of <methodname>doConnect()</methodname> to create |
| (or not create) the actual tunnel. If |
| <methodname>doConnect()</methodname> does not create the tunnel, |
| communication between the JavaScript client and guacd cannot take |
| place, which is an ideal power to have as an authenticator.</para> |
| <para>The <methodname>doConnect()</methodname> function is expected to |
| "attach" a <classname>GuacamoleTunnel</classname> to the web |
| session, abstracted by <classname>GuacamoleSession</classname>. |
| Attaching a tunnel to the session allows future tunnel requests to |
| retrieve the same tunnel and use it, thus allowing one tunnel to be |
| split across multiple requests. Assuming the |
| <methodname>doConnect()</methodname> function successfully |
| creates the tunnel, it must then return the created tunnel. The |
| already-implemented parts of |
| <classname>GuacamoleHTTPTunnelServlet</classname> then return |
| the unique identifier of this tunnel to the JavaScript client, |
| allowing its own tunnel implementation to continue to communicate |
| with the tunnel existing on the Java side.</para> |
| <para>Instances of <classname>GuacamoleTunnel</classname> are created |
| associated with a <classname>GuacamoleSocket</classname>, which is |
| the abstract interface surrounding the low-level connection to |
| guacd. Overall, there is a socket |
| (<classname>GuacamoleSocket</classname>) which provides a TCP |
| connection to guacd. This socket is exposed to |
| <classname>GuacamoleTunnel</classname>, which provides abstract |
| protocol access around what is actually (but secretly, through the |
| abstraction of the API) a TCP socket. The |
| <classname>GuacamoleSession</classname> allows instances of |
| <classname>GuacamoleTunnel</classname> to be shared across |
| requests, and <classname>GuacamoleHTTPTunnelServlet</classname> |
| pulls these tunnels from the session as necessary to fulfill |
| requests made by the JavaScript client.</para> |
| <para>The Guacamole web application extends this tunnel servlet in order |
| to implement authentication at the lowest possible level, |
| effectively prohibiting communication between the client and any |
| remote desktops unless they have properly authenticated. Your own |
| implementation can be considerably simpler, especially if you don't |
| need authentication:</para> |
| <informalexample> |
| <programlisting>public class MyGuacamoleTunnelServlet |
| extends GuacamoleHTTPTunnelServlet { |
| |
| @Override |
| protected GuacamoleTunnel doConnect(HttpServletRequest request) |
| throws GuacamoleException { |
| |
| // Connect to guacd here (this is a STUB) |
| GuacamoleSocket socket; |
| |
| // Establish the tunnel using the connected socket |
| GuacamoleTunnel tunnel = new GuacamoleTunnel(socket); |
| |
| // Attach tunnel to session |
| GuacamoleSession session = new GuacamoleSession(httpSession); |
| session.attachTunnel(tunnel); |
| |
| // Return pre-attached tunnel |
| return tunnel; |
| |
| } |
| |
| }</programlisting> |
| </informalexample> |
| </section> |
| <section xml:id="java-protocol-usage"> |
| <title>Using the Guacamole protocol</title> |
| <para>guacamole-common provides basic low-level support for the |
| Guacamole protocol. This low-level support is leveraged by the HTTP |
| tunnel implementation to satisfy the requirements of the JavaScript |
| client implementation, as the JavaScript client expects the |
| handshake procedure to have already taken place. This support exists |
| through the <classname>GuacamoleReader</classname> and |
| <classname>GuacamoleWriter</classname> classes, which are |
| similar to Java's <classname>Reader</classname> and |
| <classname>Writer</classname> classes, except that they deal |
| with the Guacamole protocol specifically, and thus have slightly |
| different contracts.</para> |
| <section xml:id="java-reading-protocol"> |
| <title><classname>GuacamoleReader</classname></title> |
| <para><classname>GuacamoleReader</classname> provides a very basic |
| <methodname>read()</methodname> function which is required |
| to return one or more complete instructions in a |
| <type>char</type> array. It also provides the typical |
| <methodname>available()</methodname> function, which informs |
| you whether <methodname>read()</methodname> is likely to block |
| the next time it is called, and an even more abstract version of |
| <methodname>read()</methodname> called |
| <methodname>readInstruction()</methodname> which returns one |
| instruction at a time, wrapped within a |
| <classname>GuacamoleInstruction</classname> instance.</para> |
| <para>Normally, you would not need to use this class yourself. It is |
| used by <classname>ConfiguredGuacamoleSocket</classname> to |
| complete the Guacamole protocol handshake procedure, and it is |
| used by <classname>GuacamoleHTTPTunnelServlet</classname> within |
| <methodname>doRead()</methodname> to implement the reading |
| half of the tunnel.</para> |
| <para>The only concrete implementation of |
| <classname>GuacamoleReader</classname> is |
| <classname>ReaderGuacamoleReader</classname>, which wraps a |
| Java <classname>Reader</classname>, using that as the source for |
| data to parse into Guacamole instructions. Again, you would not |
| normally directly use this class, nor instantiate it yourself. A |
| working, concrete instance of |
| <classname>GuacamoleReader</classname> can be retrieved from |
| any <classname>GuacamoleSocket</classname> or |
| <classname>GuacamoleTunnel</classname>.</para> |
| </section> |
| <section xml:id="java-writing-protocol"> |
| <title><classname>GuacamoleWriter</classname></title> |
| <para><classname>GuacamoleWriter</classname> provides a very basic |
| <methodname>write()</methodname> function and a more |
| abstract version called |
| <methodname>writeInstruction()</methodname> which writes |
| instances of <classname>GuacamoleInstruction</classname>. These |
| functions are analogous to the <methodname>read()</methodname> |
| and <methodname>readInstruction()</methodname> functions |
| provided by <classname>GuacamoleReader</classname>, and have |
| similar restrictions: the contract imposed by |
| <methodname>write()</methodname> requires that written |
| instructions be complete</para> |
| <para>The only concrete implementation of |
| <classname>GuacamoleWriter</classname> is |
| <classname>WriterGuacamoleWriter</classname>, which wraps a |
| Java <classname>Writer</classname>, using that as the |
| destination for Guacamole instruction data, but you would not |
| normally directly use this class, nor instantiate it yourself. |
| It is used by <classname>ConfiguredGuacamoleSocket</classname> |
| to complete the Guacamole protocol handshake procedure, and it |
| is used by <classname>GuacamoleHTTPTunnelServlet</classname> |
| within <methodname>doWrite()</methodname> to implement the |
| writing half of the tunnel.</para> |
| <para>If necessary, a <classname>GuacamoleWriter</classname> can be |
| retrieved from any <classname>GuacamoleSocket</classname> or |
| <classname>GuacamoleTunnel</classname>, but in most cases, |
| the classes provided by the Guacamole Java API which already use |
| <classname>GuacamoleWriter</classname> will be |
| sufficient.</para> |
| </section> |
| </section> |
| <section xml:id="reading-properties"> |
| <title>Reading properties</title> |
| <para>The Guacamole Java API provides simple access to |
| <filename>guacamole.properties</filename> for convenience, |
| although such support is not strictly required. This support is |
| provided through the <classname>GuacamoleProperies</classname> |
| utility class, which cannot be instantiated and provides two simple |
| property retrieval functions: <methodname>getProperty()</methodname> |
| and <methodname>getRequiredProperty()</methodname>, the difference |
| being that the former can return <constant>null</constant> if a |
| property is not defined, while the latter will throw an exception |
| instead. These functions are generic and typesafe and will return |
| the correct Java class or type when given an instance of a |
| property.</para> |
| <para>In Guacamole, each property is declared as an implementation of |
| <classname>GuacamoleProperty</classname>, and must provide an |
| implementation of <methodname>getName()</methodname>, which returns |
| the name of the property as it should exist within |
| <filename>guacamole.properties</filename>, and |
| <methodname>parseValue()</methodname>, which is given the |
| <classname>String</classname> value of the property as read from |
| <filename>guacamole.properties</filename>, and must return the |
| declared type of the <classname>GuacamoleProperty</classname> |
| implementation. A good example of how this works is the |
| <classname>IntegerGuacamoleProperty</classname> implementation |
| included within guacamole-common:</para> |
| <informalexample> |
| <programlisting>public abstract class IntegerGuacamoleProperty implements GuacamoleProperty<Integer> { |
| |
| @Override |
| public Integer parseValue(String value) throws GuacamoleException { |
| |
| // If no property provided, return null. |
| if (value == null) |
| return null; |
| |
| try { |
| Integer integer = new Integer(value); |
| return integer; |
| } |
| catch (NumberFormatException e) { |
| throw new GuacamoleServerException("Property \"" + getName() + |
| "\" must be an integer.", e); |
| } |
| |
| } |
| |
| }</programlisting> |
| </informalexample> |
| <para>Notice that this implementation does not actually provide |
| <methodname>getName()</methodname>. Instead, it only implements |
| <methodname>parseValue()</methodname>, the intent being to make |
| other developers' lives easier when they need to retrieve an integer |
| property from <filename>guacamole.properties</filename>. Using this |
| class, retrieving an integer property is simple:</para> |
| <informalexample> |
| <programlisting>public class MyClass { |
| |
| public static final IntegerGuacamoleProperty IMPORTANT_INT = |
| new IntegerGuacamoleProperty() { |
| |
| @Override |
| public String getName() { return "important-int"; } |
| |
| }; |
| |
| } |
| |
| ... later on within MyClass ... |
| |
| int important = GuacamoleProperties.getRequiredProperty(IMPORTANT_INT);</programlisting> |
| </informalexample> |
| <para>guacamole-common provides a couple of similar classes for |
| retrieving common types of properties, such as a |
| <classname>String</classname> or <classname>File</classname>, |
| and implementing your own to facilitate properties that parse into |
| arrays or a <classname>List</classname>, etc. should be reasonably |
| simple.</para> |
| </section> |
| </chapter> |