| <?xml version="1.0" encoding="UTF-8"?> |
| <chapter xml:id="libguac" 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>libguac</title> |
| <indexterm> |
| <primary>API</primary> |
| <secondary>C</secondary> |
| </indexterm> |
| <indexterm> |
| <primary>libguac</primary> |
| </indexterm> |
| <para>The C API for extending and developing with Guacamole is libguac. All |
| native components produced by the Guacamole project link with this |
| library, and this library provides the common basis for extending the |
| native functionality of those native components (by implementing client |
| plugins).</para> |
| <para>libguac is used mainly for developing client plugins like |
| libguac-client-vnc or libguac-client-rdp, or for developing a proxy |
| supporting the Guacamole protocol like guacd. This chapter is intended |
| to give an overview of how libguac is used, and how to use it for |
| general communication with the Guacamole protocol.</para> |
| <section xml:id="libguac-error-handling"> |
| <title>Error handling</title> |
| <para>Most functions within libguac handle errors by returning a zero or |
| non-zero value, whichever is appropriate for the function at hand. |
| If an error is encountered, the <varname>guac_error</varname> |
| variable is set appropriately, and |
| <varname>guac_error_message</varname> contains a |
| statically-allocated human-readable string describing the context of |
| the error. These variables intentionally mimic the functionality |
| provided by <varname>errno</varname> and |
| <filename>errno.h</filename>.</para> |
| <para>Both <varname>guac_error</varname> and |
| <varname>guac_error_message</varname> are defined within |
| <filename>error.h</filename>. A human-readable string describing |
| the error indicated by <varname>guac_error</varname> can be |
| retrieved using <methodname>guac_status_string()</methodname>, which |
| is also statically allocated.</para> |
| <para>If functions defined within client plugins set |
| <varname>guac_error</varname> and |
| <varname>guac_error_message</varname> appropriately when errors |
| are encountered, the messages logged to syslog by guacd will be more |
| meaningful for both users and developers.</para> |
| </section> |
| <section xml:id="libguac-client-plugins"> |
| <title>Client plugins</title> |
| <para>Client plugins are libraries which follow specific conventions such that they can be |
| loaded dynamically by guacd. All client plugins <emphasis>must</emphasis>:</para> |
| <orderedlist> |
| <listitem> |
| <para>Follow a naming convention, where the name of the library is |
| <package>libguac-client-<replaceable>PROTOCOL</replaceable></package>. |
| <emphasis>This is necessary for guacd to locate the library for a requested |
| protocol.</emphasis></para> |
| </listitem> |
| <listitem> |
| <para>Be linked against libguac, the library used by guacd to handle the Guacamole |
| protocol. The structures which are given to functions invoked by guacd are |
| defined by libguac, and are expected to be manipulated via the functions |
| provided by libguac or as otherwise documented within the structure itself. |
| <emphasis>Communication between guacd and client plugins is only possible if |
| they share the same core structural and functional definitions provided by |
| libguac.</emphasis></para> |
| </listitem> |
| <listitem> |
| <para>Implement the standard entry point for client plugins, |
| <methodname>guac_client_init()</methodname>, described in more detail below. |
| It is this function which initializes the structures provided by guacd such that |
| users can join and interact with the connection.</para> |
| </listitem> |
| </orderedlist> |
| <section xml:id="libguac-lifecycle-entry"> |
| <title>Entry point</title> |
| <para>All client plugins must provide a function named |
| <methodname>guac_client_init</methodname> which accepts, as its sole argument, a |
| pointer to a <classname>guac_client</classname> structure. This function is similar |
| in principle to the <methodname>main()</methodname> function of a C program, and it |
| is the responsibility of this function to initialize the provided structure as |
| necessary to begin the actual remote desktop connection, allow users to join/leave, |
| etc.</para> |
| <para>The provided <classname>guac_client</classname> will already have been initialized |
| with handlers for logging, the broadcast socket, etc. The absolutely critical pieces |
| which must be provided by <methodname>guac_client_init</methodname> are:</para> |
| <orderedlist> |
| <listitem> |
| <para>A handler for users which join the connection |
| (<property>join_handler</property>). The join handler is also usually |
| the most appropriate place for the actual remote desktop connection to be |
| established.</para> |
| </listitem> |
| <listitem> |
| <para>A <constant>NULL</constant>-terminated set of argument names which the |
| client plugin accepts, assigned to the <property>args</property> property of |
| the given <classname>guac_client</classname>. As the handshake procedure is |
| completed for each connecting user, these argument names will be presented |
| as part of the handshake, and the values for those arguments will be passed |
| to the join handler once the handshake completes.</para> |
| </listitem> |
| <listitem> |
| <para>A handler for users leaving the connection |
| (<property>leave_handler</property>), if any cleanup, updates, etc. are |
| required.</para> |
| </listitem> |
| <listitem> |
| <para>A handler for freeing the data associated with the |
| <classname>guac_client</classname> after the connection has terminated |
| (<property>free_handler</property>). If your plugin will allocate any |
| data at all, implementing the free handler is necessary to avoid memory |
| leaks.</para> |
| </listitem> |
| </orderedlist> |
| <para>If <methodname>guac_client_init</methodname> returns successfully, guacd will |
| proceed with allowing the first use to join the connection, and the rest of the |
| plugin lifecycle commences.</para> |
| </section> |
| <section xml:id="libguac-lifecycle-users"> |
| <title>Joining/leaving a connection</title> |
| <para>Whenever a user joins a connection, including the very first user of a connection |
| (the user which is establishing the remote desktop connection in the first place), |
| the join handler of the <property>guac_client</property> will be invoked. This |
| handler is provided with the <classname>guac_user</classname> structure representing |
| the user that just joined, along with the arguments provided during the handshake |
| procedure:</para> |
| <informalexample> |
| <programlisting>int join_handler(guac_user* user, int argc, char** argv) { |
| /* Synchronize display state, init the user, etc. */ |
| } |
| |
| ... |
| |
| /* Within guac_client_init */ |
| client->join_handler = join_handler;</programlisting> |
| </informalexample> |
| <para>As the parameters and user information provided during the Guacamole protocol |
| handshake are often required to be known before the remote desktop connection can be |
| established, the join handler is usually the best place to create a thread which |
| establishes the remote desktop connection and updates the display |
| accordingly.</para> |
| <para>If necessary, the user which first established the connection can be distinguished |
| from all other users by the <property>owner</property> flag of |
| <classname>guac_user</classname>, which will be set to a non-zero value.</para> |
| <para>Once a user has disconnected, the leave handler of |
| <classname>guac_client</classname> will be invoked. Just as with the join |
| handler, this handler is provided the <classname>guac_user</classname> structure of |
| the user that disconnected. The <classname>guac_user</classname> structure will be |
| freed immediately after the handler completes:</para> |
| <informalexample> |
| <programlisting>int leave_handler(guac_user* user) { |
| /* Free user-specific data and clean up */ |
| } |
| |
| ... |
| |
| /* Within guac_client_init */ |
| client->leave_handler = leave_handler;</programlisting> |
| </informalexample> |
| </section> |
| <section xml:id="libguac-lifecycle-termination"> |
| <title>Termination</title> |
| <para>Once the last user of a connection has left, guacd will begin freeing resources |
| allocated to that connection, invoking the free handler of the |
| <classname>guac_client</classname>. At this point, the "leave" handler has been |
| invoked for all previous users. All that remains is for the client plugin to free |
| any remaining data that it allocated, such that guacd can clean up the rest:</para> |
| <informalexample> |
| <programlisting>int free_handler(guac_client* client) { |
| /* Disconnect, free client-specific data, etc. */ |
| } |
| |
| ... |
| |
| /* Within guac_client_init */ |
| client->free_handler = free_handler;</programlisting> |
| </informalexample> |
| </section> |
| </section> |
| <section xml:id="libguac-layers"> |
| <title>Layers and buffers</title> |
| <para>The main operand of all drawing instructions is the layer, |
| represented within libguac by the <classname>guac_layer</classname> |
| structure. Each <classname>guac_layer</classname> is normally |
| allocated using <methodname>guac_client_alloc_layer()</methodname> |
| or <methodname>guac_client_alloc_buffer()</methodname>, depending on |
| whether a layer or buffer is desired, and freed with |
| <methodname>guac_client_free_layer()</methodname> or |
| <methodname>guac_client_free_buffer()</methodname>.</para> |
| <important> |
| <para>Care must be taken to invoke the allocate and free pairs of |
| each type of layer correctly. |
| <methodname>guac_client_free_layer()</methodname> should |
| only be used to free layers allocated with |
| <methodname>guac_client_alloc_layer()</methodname>, and |
| <methodname>guac_client_free_buffer()</methodname> should |
| only be used to free layers allocated with |
| <methodname>guac_client_alloc_buffer()</methodname>, all |
| called using the same instance of |
| <classname>guac_client</classname>.</para> |
| <para>If these restrictions are not observed, the effect of invoking |
| these functions is undefined.</para> |
| </important> |
| <para>Using these layer management functions allows you to reuse |
| existing layers or buffers after their original purpose has expired, |
| thus conserving resources on the client side, as allocation of new |
| layers within the remote client is a relatively expensive |
| operation.</para> |
| <para>It is through layers and buffers that Guacamole provides support |
| for hardware-accelerated compositing and cached updates. Creative |
| use of layers and buffers leads to efficient updates on the client |
| side, which usually translates into speed and responsiveness.</para> |
| <para>Regardless of whether you allocate new layers or buffers, there is |
| always one layer guaranteed to be present: the default layer, |
| represented by libguac as <varname>GUAC_DEFAULT_LAYER</varname>. If |
| you only wish to affect to the main display of the connected client |
| somehow, this is the layer you want to use as the operand of your |
| drawing instruction.</para> |
| </section> |
| <section xml:id="libguac-streams"> |
| <title>Streams</title> |
| <para>In addition to drawing, the Guacamole protocol supports streaming of arbitrary data. |
| The main operand of all streaming instructions is the stream, represented within libguac |
| by the <classname>guac_stream</classname> structure. Each |
| <classname>guac_stream</classname> exists either at the user or client levels, |
| depending on whether the stream is intended to be broadcast to all users or just one, |
| and is thus allocated using either <methodname>guac_client_alloc_stream()</methodname> |
| or <methodname>guac_user_alloc_stream()</methodname>. Explicitly-allocated streams must |
| eventually be freed with <methodname>guac_client_free_stream()</methodname> or |
| <methodname>guac_user_free_stream()</methodname>.</para> |
| <important> |
| <para>Just as with layers, care must be taken to invoke the allocate and free pairs |
| correctly for each explicitly-allocated stream. |
| <methodname>guac_client_free_stream()</methodname> should only be used to free |
| streams allocated with <methodname>guac_client_alloc_stream()</methodname>, and |
| <methodname>guac_user_free_stream()</methodname> should only be used to free |
| streams allocated with <methodname>guac_user_alloc_stream()</methodname>.</para> |
| <para>If these restrictions are not observed, the effect of invoking these functions is |
| undefined.</para> |
| </important> |
| <para>Streams are the means by which data is transmitted for clipboard (via the <link |
| xmlns:xlink="http://www.w3.org/1999/xlink" linkend="clipboard-instruction" |
| >"clipboard" instruction</link>), audio (via the <link |
| xmlns:xlink="http://www.w3.org/1999/xlink" linkend="audio-stream-instruction" |
| >"audio" instruction</link>), and even the images which make up typical drawing |
| operations (via the <link xmlns:xlink="http://www.w3.org/1999/xlink" |
| linkend="img-instruction">"img" instruction</link>). They will either be allocated |
| for you, when an inbound stream is received from a user, or allocated manually, when an |
| outbound stream needs to be sent to a user. As with <classname>guac_client</classname> |
| and <classname>guac_user</classname>, each <classname>guac_stream</classname> has a set |
| of handlers which correspond to instructions received related to streams. These |
| instructions are documented in more detail in <xref |
| xmlns:xlink="http://www.w3.org/1999/xlink" linkend="guacamole-protocol-streaming"/> |
| and <xref xmlns:xlink="http://www.w3.org/1999/xlink" linkend="protocol-reference" |
| />.</para> |
| </section> |
| <section xml:id="libguac-sending-instructions"> |
| <title>Sending instructions</title> |
| <para>All drawing in Guacamole is accomplished through the sending of instructions to the |
| connected client using the Guacamole protocol. The same goes for streaming audio, video, |
| or file content. All features and content supported by Guacamole ultimately reduce to |
| one or more instructions which are part of the documented protocol.</para> |
| <para>Most drawing using libguac is done using Cairo functions on a |
| <classname>cairo_surface_t</classname> (see the Cairo API documentation) which is |
| later streamed to the client using an <methodname>img</methodname> instruction and |
| subsequent <methodname>blob</methodname> instructions, sent via |
| <methodname>guac_client_stream_png()</methodname>. Cairo was chosen as a dependency |
| of libguac to provide developers an existing and stable means of drawing to image |
| buffers which will ultimately be sent as easy-to-digest PNG images.</para> |
| <para>The Guacamole protocol also supports drawing primitives similar to |
| those present in the Cairo API and HTML5's canvas tag. These |
| instructions are documented individually in the Guacamole Protocol |
| Reference in a section dedicated to drawing instructions, and like |
| all Guacamole protocol instructions, each instruction has a |
| corresponding function in libguac following the naming convention |
| <methodname>guac_protocol_send_<replaceable>OPCODE</replaceable>()</methodname>.</para> |
| <para>Each protocol function takes a <classname>guac_socket</classname> as an argument, |
| which is the buffered I/O object used by libguac. For each active connection, there are |
| two important types of <classname>guac_socket</classname> instance: the broadcast |
| socket, which exists at the client level within the <classname>guac_client</classname>, |
| and the per-user socket, which is accessible within each |
| <classname>guac_user</classname>. Data sent along the client-level broadcast socket |
| will be sent to all connected users beneath that <classname>guac_client</classname>, |
| while data sent along a user-level socket will be sent only to that user.</para> |
| <para>For example, to send a "size" instruction to all connected users via the client-level |
| broadcast socket, you could invoke:</para> |
| <informalexample> |
| <programlisting>guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, 1024, 768);</programlisting> |
| </informalexample> |
| <para>Or, if the instruction is only relevant to a particular user, the socket associated |
| with that user can be used instead:</para> |
| <informalexample> |
| <programlisting>guac_protocol_send_size(<emphasis>user</emphasis>->socket, GUAC_DEFAULT_LAYER, 1024, 768);</programlisting> |
| </informalexample> |
| <para>The sockets provided by libguac are threadsafe at the protocol level. Instructions |
| written to a socket by multiple threads are guaranteed to be written atomically with |
| respect to that socket.</para> |
| </section> |
| <section xml:id="libguac-event-handling"> |
| <title>Event handling</title> |
| <para>Generally, as guacd receives instructions from the connected client, it invokes event |
| handlers if set within the associated <classname>guac_user</classname> or |
| <classname>guac_client</classname>, depending on the nature of the event. Most |
| events are user-specific, and thus the event handlers reside within the |
| <classname>guac_user</classname> structure, but there are client-specific events as |
| well, such as a user joining or leaving the current connection. Event handlers typically |
| correspond to Guacamole protocol instructions received over the socket by a connected |
| user, which in turn correspond to events which occur on the client side.</para> |
| <section xml:id="libguac-key-events"> |
| <title>Key events</title> |
| <para>When keys are pressed or released on the client side, the client sends key |
| instructions to the server. These instructions are parsed and handled by calling the |
| key event handler installed in the <property>key_handler</property> member of the |
| <classname>guac_user</classname>. This key handler is given the keysym of the |
| key that was changed, and a boolean value indicating whether the key was pressed or |
| released.</para> |
| <informalexample> |
| <programlisting>int key_handler(guac_user* user, int keysym, int pressed) { |
| /* Do something */ |
| } |
| |
| ... |
| |
| /* Within the "join" handler of guac_client */ |
| user->key_handler = key_handler;</programlisting> |
| </informalexample> |
| </section> |
| <section xml:id="libguac-mouse-events"> |
| <title>Mouse events</title> |
| <para>When the mouse is moved, and buttons are pressed or released, the client sends |
| mouse instructions to the server. These instructions are parsed and handled by |
| calling the mouse event handler installed in the <property>mouse_handler</property> |
| member of the <classname>guac_user</classname>. This mouse handler is given the |
| current X and Y coordinates of the mouse pointer, as well as a mask indicating which |
| buttons are pressed and which are released.</para> |
| <informalexample> |
| <programlisting>int mouse_handler(guac_user* user, int x, int y, int button_mask) { |
| /* Do something */ |
| } |
| |
| ... |
| |
| /* Within the "join" handler of guac_client */ |
| user->mouse_handler = mouse_handler;</programlisting> |
| </informalexample> |
| <para>The file <filename>client.h</filename> also defines the mask |
| of each button for convenience:</para> |
| <variablelist> |
| <varlistentry> |
| <term><constant>GUAC_CLIENT_MOUSE_LEFT</constant></term> |
| <listitem> |
| <para>The left mouse button, set when pressed.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><constant>GUAC_CLIENT_MOUSE_MIDDLE</constant></term> |
| <listitem> |
| <para>The middle mouse button, set when pressed.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><constant>GUAC_CLIENT_MOUSE_RIGHT</constant></term> |
| <listitem> |
| <para>The right mouse button, set when pressed.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><constant>GUAC_CLIENT_MOUSE_UP</constant></term> |
| <listitem> |
| <para>The button corresponding to one scroll in the |
| upwards direction of the mouse scroll wheel, set |
| when scrolled.</para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><constant>GUAC_CLIENT_MOUSE_DOWN</constant></term> |
| <listitem> |
| <para>The button corresponding to one scroll in the |
| downwards direction of the mouse scroll wheel, set |
| when scrolled.</para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </section> |
| <section xml:id="libguac-clipboard-events"> |
| <title>Clipboard, file, and other stream events</title> |
| <para>If a connected user sends data which should be sent to the clipboard of the remote |
| desktop, guacd will trigger the clipboard handler installed in the |
| <property>clipboard_handler</property> member of the |
| <classname>guac_user</classname> associated with that user.</para> |
| <informalexample> |
| <programlisting>int clipboard_handler(guac_user* user, guac_stream* stream, char* mimetype) { |
| /* Do something */ |
| } |
| |
| ... |
| |
| /* Within the "join" handler of guac_client */ |
| user->clipboard_handler = clipboard_handler;</programlisting> |
| </informalexample> |
| <para>The handler is expected to assign further handlers to the provided |
| <classname>guac_stream</classname> as necessary, such that the <link |
| xmlns:xlink="http://www.w3.org/1999/xlink" linkend="blob-instruction" |
| >"blob"</link> and <link xmlns:xlink="http://www.w3.org/1999/xlink" |
| linkend="end-instruction">"end"</link> instructions received along the stream |
| can be handled. A similar handler is provided for received files:</para> |
| <informalexample> |
| <programlisting>int file_handler(guac_user* user, guac_stream* stream, |
| char* mimetype, char* filename) { |
| /* Do something */ |
| } |
| |
| ... |
| |
| /* Within the "join" handler of guac_client */ |
| user->file_handler = file_handler;</programlisting> |
| </informalexample> |
| <para>This pattern continues for all other types of streams which can be received from a |
| user. The instruction which begins the stream has a corresponding handler within |
| <classname>guac_user</classname>, and the metadata describing that stream and |
| provided with the instruction is included within the parameters passed to that |
| handler.</para> |
| <para>These handlers are, of course, optional. If any type of stream lacks a |
| corresponding handler, guacd will automatically close the stream and respond with an |
| <link xmlns:xlink="http://www.w3.org/1999/xlink" linkend="ack-instruction">"ack" |
| instruction</link> and appropriate error code, informing the user's Guacamole |
| client that the stream is unsupported.</para> |
| </section> |
| </section> |
| </chapter> |