| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #ifndef _GUAC_CLIENT_H |
| #define _GUAC_CLIENT_H |
| |
| /** |
| * Functions and structure contents for the Guacamole proxy client. |
| * |
| * @file client.h |
| */ |
| |
| #include "client-fntypes.h" |
| #include "client-types.h" |
| #include "client-constants.h" |
| #include "layer-types.h" |
| #include "object-types.h" |
| #include "pool-types.h" |
| #include "socket-types.h" |
| #include "stream-types.h" |
| #include "timestamp-types.h" |
| #include "user-fntypes.h" |
| #include "user-types.h" |
| |
| #include <cairo/cairo.h> |
| |
| #include <pthread.h> |
| #include <stdarg.h> |
| |
| struct guac_client { |
| |
| /** |
| * The guac_socket structure to be used to communicate with all connected |
| * web-clients (users). Unlike the user-level guac_socket, this guac_socket |
| * will broadcast instructions to all connected users simultaneously. It |
| * is expected that the implementor of any Guacamole proxy client will |
| * provide their own mechanism of I/O for their protocol. The guac_socket |
| * structure is used only to communicate conveniently with the Guacamole |
| * web-client. |
| */ |
| guac_socket* socket; |
| |
| /** |
| * The current state of the client. When the client is first allocated, |
| * this will be initialized to GUAC_CLIENT_RUNNING. It will remain at |
| * GUAC_CLIENT_RUNNING until an event occurs which requires the client to |
| * shutdown, at which point the state becomes GUAC_CLIENT_STOPPING. |
| */ |
| guac_client_state state; |
| |
| /** |
| * Arbitrary reference to proxy client-specific data. Implementors of a |
| * Guacamole proxy client can store any data they want here, which can then |
| * be retrieved as necessary in the message handlers. |
| */ |
| void* data; |
| |
| /** |
| * The time (in milliseconds) that the last sync message was sent to the |
| * client. |
| */ |
| guac_timestamp last_sent_timestamp; |
| |
| /** |
| * Handler for freeing data when the client is being unloaded. |
| * |
| * This handler will be called when the client needs to be unloaded |
| * by the proxy, and any data allocated by the proxy client should be |
| * freed. |
| * |
| * Note that this handler will NOT be called if the client's |
| * guac_client_init() function fails. |
| * |
| * Implement this handler if you store data inside the client. |
| * |
| * Example: |
| * @code |
| * int free_handler(guac_client* client); |
| * |
| * int guac_client_init(guac_client* client) { |
| * client->free_handler = free_handler; |
| * } |
| * @endcode |
| */ |
| guac_client_free_handler* free_handler; |
| |
| /** |
| * Logging handler. This handler will be called via guac_client_log() when |
| * the client needs to log messages of any type. |
| * |
| * In general, only programs loading the client should implement this |
| * handler, as those are the programs that would provide the logging |
| * facilities. |
| * |
| * Client implementations should expect these handlers to already be |
| * set. |
| * |
| * Example: |
| * @code |
| * void log_handler(guac_client* client, guac_client_log_level level, const char* format, va_list args); |
| * |
| * void function_of_daemon() { |
| * |
| * guac_client* client = [pass log_handler to guac_client_plugin_get_client()]; |
| * |
| * } |
| * @endcode |
| */ |
| guac_client_log_handler* log_handler; |
| |
| /** |
| * Pool of buffer indices. Buffers are simply layers with negative indices. |
| * Note that because guac_pool always gives non-negative indices starting |
| * at 0, the output of this guac_pool will be adjusted. |
| */ |
| guac_pool* __buffer_pool; |
| |
| /** |
| * Pool of layer indices. Note that because guac_pool always gives |
| * non-negative indices starting at 0, the output of this guac_pool will |
| * be adjusted. |
| */ |
| guac_pool* __layer_pool; |
| |
| /** |
| * Pool of stream indices. |
| */ |
| guac_pool* __stream_pool; |
| |
| /** |
| * All available client-level output streams (data going to all connected |
| * users). |
| */ |
| guac_stream* __output_streams; |
| |
| /** |
| * The unique identifier allocated for the connection, which may |
| * be used within the Guacamole protocol to refer to this connection. |
| * This identifier is guaranteed to be unique from all existing |
| * connections and will not collide with any available protocol |
| * names. |
| */ |
| char* connection_id; |
| |
| /** |
| * Lock which is acquired when the users list is being manipulated, or when |
| * the users list is being iterated. |
| */ |
| pthread_rwlock_t __users_lock; |
| |
| /** |
| * The first user within the list of all connected users, or NULL if no |
| * users are currently connected. |
| */ |
| guac_user* __users; |
| |
| /** |
| * The user that first created this connection. This user will also have |
| * their "owner" flag set to a non-zero value. If the owner has left the |
| * connection, this will be NULL. |
| */ |
| guac_user* __owner; |
| |
| /** |
| * The number of currently-connected users. This value may include inactive |
| * users if cleanup of those users has not yet finished. |
| */ |
| int connected_users; |
| |
| /** |
| * Handler for join events, called whenever a new user is joining an active |
| * connection. Note that because users may leave the connection at any |
| * time, a reference to a guac_user can become invalid at any time and |
| * should never be maintained outside the scope of a function invoked by |
| * libguac to which that guac_user was passed (the scope in which the |
| * guac_user reference is guaranteed to be valid) UNLESS that reference is |
| * properly invalidated within the leave_handler. |
| * |
| * The handler is given a pointer to a newly-allocated guac_user which |
| * must then be initialized, if needed. |
| * |
| * Example: |
| * @code |
| * int join_handler(guac_user* user, int argc, char** argv); |
| * |
| * int guac_client_init(guac_client* client) { |
| * client->join_handler = join_handler; |
| * } |
| * @endcode |
| */ |
| guac_user_join_handler* join_handler; |
| |
| /** |
| * Handler for leave events, called whenever a new user is leaving an |
| * active connection. |
| * |
| * The handler is given a pointer to the leaving guac_user whose custom |
| * data and associated resources must now be freed, if any. |
| * |
| * Example: |
| * @code |
| * int leave_handler(guac_user* user); |
| * |
| * int guac_client_init(guac_client* client) { |
| * client->leave_handler = leave_handler; |
| * } |
| * @endcode |
| */ |
| guac_user_leave_handler* leave_handler; |
| |
| /** |
| * NULL-terminated array of all arguments accepted by this client , in |
| * order. New users will specify these arguments when they join the |
| * connection, and the values of those arguments will be made available to |
| * the function initializing newly-joined users. |
| * |
| * The guac_client_init entry point is expected to initialize this, if |
| * arguments are expected. |
| * |
| * Example: |
| * @code |
| * const char* __my_args[] = { |
| * "hostname", |
| * "port", |
| * "username", |
| * "password", |
| * NULL |
| * }; |
| * |
| * int guac_client_init(guac_client* client) { |
| * client->args = __my_args; |
| * } |
| * @endcode |
| */ |
| const char** args; |
| |
| /** |
| * Handle to the dlopen()'d plugin, which should be given to dlclose() when |
| * this client is freed. This is only assigned if guac_client_load_plugin() |
| * is used. |
| */ |
| void* __plugin_handle; |
| |
| }; |
| |
| /** |
| * Returns a new, barebones guac_client. This new guac_client has no handlers |
| * set, but is otherwise usable. |
| * |
| * @return A pointer to the new client. |
| */ |
| guac_client* guac_client_alloc(); |
| |
| /** |
| * Free all resources associated with the given client. |
| * |
| * @param client The proxy client to free all reasources of. |
| */ |
| void guac_client_free(guac_client* client); |
| |
| /** |
| * Writes a message in the log used by the given client. The logger used will |
| * normally be defined by guacd (or whichever program loads the proxy client) |
| * by setting the logging handlers of the client when it is loaded. |
| * |
| * @param client The proxy client logging this message. |
| * @param level The level at which to log this message. |
| * @param format A printf-style format string to log. |
| * @param ... Arguments to use when filling the format string for printing. |
| */ |
| void guac_client_log(guac_client* client, guac_client_log_level level, |
| const char* format, ...); |
| |
| /** |
| * Writes a message in the log used by the given client. The logger used will |
| * normally be defined by guacd (or whichever program loads the proxy client) |
| * by setting the logging handlers of the client when it is loaded. |
| * |
| * @param client The proxy client logging this message. |
| * @param level The level at which to log this message. |
| * @param format A printf-style format string to log. |
| * @param ap The va_list containing the arguments to be used when filling the |
| * format string for printing. |
| */ |
| void vguac_client_log(guac_client* client, guac_client_log_level level, |
| const char* format, va_list ap); |
| |
| /** |
| * Signals the given client to stop gracefully. This is a completely |
| * cooperative signal, and can be ignored by the client or the hosting |
| * daemon. |
| * |
| * @param client The proxy client to signal to stop. |
| */ |
| void guac_client_stop(guac_client* client); |
| |
| /** |
| * Signals the given client to stop gracefully, while also signalling via the |
| * Guacamole protocol that an error has occurred. Note that this is a completely |
| * cooperative signal, and can be ignored by the client or the hosting |
| * daemon. The message given will be logged to the system logs. |
| * |
| * @param client The proxy client to signal to stop. |
| * @param status The status to send over the Guacamole protocol. |
| * @param format A printf-style format string to log. |
| * @param ... Arguments to use when filling the format string for printing. |
| */ |
| void guac_client_abort(guac_client* client, guac_protocol_status status, |
| const char* format, ...); |
| |
| /** |
| * Signals the given client to stop gracefully, while also signalling via the |
| * Guacamole protocol that an error has occurred. Note that this is a completely |
| * cooperative signal, and can be ignored by the client or the hosting |
| * daemon. The message given will be logged to the system logs. |
| * |
| * @param client The proxy client to signal to stop. |
| * @param status The status to send over the Guacamole protocol. |
| * @param format A printf-style format string to log. |
| * @param ap The va_list containing the arguments to be used when filling the |
| * format string for printing. |
| */ |
| void vguac_client_abort(guac_client* client, guac_protocol_status status, |
| const char* format, va_list ap); |
| |
| /** |
| * Allocates a new buffer (invisible layer). An arbitrary index is |
| * automatically assigned if no existing buffer is available for use. |
| * |
| * @param client The proxy client to allocate the buffer for. |
| * @return The next available buffer, or a newly allocated buffer. |
| */ |
| guac_layer* guac_client_alloc_buffer(guac_client* client); |
| |
| /** |
| * Allocates a new layer. An arbitrary index is automatically assigned |
| * if no existing layer is available for use. |
| * |
| * @param client The proxy client to allocate the layer buffer for. |
| * @return The next available layer, or a newly allocated layer. |
| */ |
| guac_layer* guac_client_alloc_layer(guac_client* client); |
| |
| /** |
| * Returns the given buffer to the pool of available buffers, such that it |
| * can be reused by any subsequent call to guac_client_allow_buffer(). |
| * |
| * @param client The proxy client to return the buffer to. |
| * @param layer The buffer to return to the pool of available buffers. |
| */ |
| void guac_client_free_buffer(guac_client* client, guac_layer* layer); |
| |
| /** |
| * Returns the given layer to the pool of available layers, such that it |
| * can be reused by any subsequent call to guac_client_allow_layer(). |
| * |
| * @param client The proxy client to return the layer to. |
| * @param layer The buffer to return to the pool of available layer. |
| */ |
| void guac_client_free_layer(guac_client* client, guac_layer* layer); |
| |
| /** |
| * Allocates a new stream. An arbitrary index is automatically assigned |
| * if no previously-allocated stream is available for use. |
| * |
| * @param client |
| * The client to allocate the stream for. |
| * |
| * @return |
| * The next available stream, or a newly allocated stream. |
| */ |
| guac_stream* guac_client_alloc_stream(guac_client* client); |
| |
| /** |
| * Returns the given stream to the pool of available streams, such that it |
| * can be reused by any subsequent call to guac_client_alloc_stream(). |
| * |
| * @param client |
| * The client to return the stream to. |
| * |
| * @param stream |
| * The stream to return to the pool of available stream. |
| */ |
| void guac_client_free_stream(guac_client* client, guac_stream* stream); |
| |
| /** |
| * Adds the given user to the internal list of connected users. Future writes |
| * to the broadcast socket stored within guac_client will also write to this |
| * user. The join handler of this guac_client will be called. |
| * |
| * @param client The proxy client to add the user to. |
| * @param user The user to add. |
| * @param argc The number of arguments to pass to the new user. |
| * @param argv An array of strings containing the argument values being passed. |
| * @return Zero if the user was added successfully, non-zero if the user could |
| * not join the connection. |
| */ |
| int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** argv); |
| |
| /** |
| * Removes the given user, removing the user from the internally-tracked list |
| * of connected users, and calling any appropriate leave handler. |
| * |
| * @param client The proxy client to return the buffer to. |
| * @param user The user to remove. |
| */ |
| void guac_client_remove_user(guac_client* client, guac_user* user); |
| |
| /** |
| * Calls the given function on all currently-connected users of the given |
| * client. The function will be given a reference to a guac_user and the |
| * specified arbitrary data. The value returned by the callback will be |
| * ignored. |
| * |
| * This function is reentrant, but the user list MUST NOT be manipulated |
| * within the same thread as a callback to this function. Though the callback |
| * MAY invoke guac_client_foreach_user(), doing so should not be necessary, and |
| * may indicate poor design choices. |
| * |
| * @param client |
| * The client whose users should be iterated. |
| * |
| * @param callback |
| * The function to call for each user. |
| * |
| * @param data |
| * Arbitrary data to pass to the callback each time it is invoked. |
| */ |
| void guac_client_foreach_user(guac_client* client, |
| guac_user_callback* callback, void* data); |
| |
| /** |
| * Calls the given function with the currently-connected user that is marked as |
| * the owner. The owner of a connection is the user that established the |
| * initial connection that created the connection (the first user to connect |
| * and join). The function will be given a reference to the guac_user and the |
| * specified arbitrary data. If the owner has since left the connection, the |
| * function will instead be invoked with NULL as the guac_user. The value |
| * returned by the callback will be returned by this function. |
| * |
| * This function is reentrant, but the user list MUST NOT be manipulated |
| * within the same thread as a callback to this function. |
| * |
| * @param client |
| * The client to retrieve the owner from. |
| * |
| * @param callback |
| * The callback to invoke on the user marked as the owner of the |
| * connection. NULL will be passed to this callback instead if there is no |
| * owner. |
| * |
| * @param data |
| * Arbitrary data to pass to the given callback. |
| * |
| * @return |
| * The value returned by the callback. |
| */ |
| void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, |
| void* data); |
| |
| /** |
| * Calls the given function with the given user ONLY if they are currently |
| * connected. The function will be given a reference to the guac_user and the |
| * specified arbitrary data. If the provided user doesn't exist or has since |
| * left the connection, the function will instead be invoked with NULL as the |
| * guac_user. The value returned by the callback will be returned by this |
| * function. |
| * |
| * This function is reentrant, but the user list MUST NOT be manipulated |
| * within the same thread as a callback to this function. |
| * |
| * @param client |
| * The client that the given user is expected to be associated with. |
| * |
| * @param user |
| * The user to provide to the given callback if valid. The pointer need not |
| * even point to properly allocated memory; the user will only be passed to |
| * the callback function if they are valid, and the provided user pointer |
| * will not be dereferenced during this process. |
| * |
| * @param callback |
| * The callback to invoke on the given user if they are valid. NULL will be |
| * passed to this callback instead if the user is not valid. |
| * |
| * @param data |
| * Arbitrary data to pass to the given callback. |
| * |
| * @return |
| * The value returned by the callback. |
| */ |
| void* guac_client_for_user(guac_client* client, guac_user* user, |
| guac_user_callback* callback, void* data); |
| |
| /** |
| * Marks the end of the current frame by sending a "sync" instruction to |
| * all connected users. This instruction will contain the current timestamp. |
| * The last_sent_timestamp member of guac_client will be updated accordingly. |
| * |
| * If an error occurs sending the instruction, a non-zero value is |
| * returned, and guac_error is set appropriately. |
| * |
| * @param client The guac_client which has finished a frame. |
| * @return Zero on success, non-zero on error. |
| */ |
| int guac_client_end_frame(guac_client* client); |
| |
| /** |
| * Initializes the given guac_client using the initialization routine provided |
| * by the plugin corresponding to the named protocol. This will automatically |
| * invoke guac_client_init within the plugin for the given protocol. |
| * |
| * Note that the connection will likely not be established until the first |
| * user (the "owner") is added to the client. |
| * |
| * @param client The guac_client to initialize. |
| * @param protocol The name of the protocol to use. |
| * @return Zero if initialization was successful, non-zero otherwise. |
| */ |
| int guac_client_load_plugin(guac_client* client, const char* protocol); |
| |
| /** |
| * Calculates and returns the approximate processing lag experienced by the |
| * pool of users. The processing lag is the difference in time between server |
| * and client due purely to data processing and excluding network delays. |
| * |
| * @param client |
| * The guac_client to calculate the processing lag of. |
| * |
| * @return |
| * The approximate processing lag of the pool of users associated with the |
| * given guac_client, in milliseconds. |
| */ |
| int guac_client_get_processing_lag(guac_client* client); |
| |
| /** |
| * Streams the given connection parameter value over an argument value stream |
| * ("argv" instruction), exposing the current value of the named connection |
| * parameter to all users of the given client. The argument value stream will |
| * be automatically allocated and freed. |
| * |
| * @param client |
| * The Guacamole client for which the argument value stream should be |
| * allocated. |
| * |
| * @param socket |
| * The socket over which instructions associated with the argument value |
| * stream should be sent. |
| * |
| * @param mimetype |
| * The mimetype of the data within the connection parameter value being |
| * sent. |
| * |
| * @param name |
| * The name of the connection parameter being sent. |
| * |
| * @param value |
| * The current value of the connection parameter being sent. |
| */ |
| void guac_client_stream_argv(guac_client* client, guac_socket* socket, |
| const char* mimetype, const char* name, const char* value); |
| |
| /** |
| * Streams the image data of the given surface over an image stream ("img" |
| * instruction) as PNG-encoded data. The image stream will be automatically |
| * allocated and freed. |
| * |
| * @param client |
| * The Guacamole client for which the image stream should be allocated. |
| * |
| * @param socket |
| * The socket over which instructions associated with the image stream |
| * should be sent. |
| * |
| * @param mode |
| * The composite mode to use when rendering the image over the given layer. |
| * |
| * @param layer |
| * The destination layer. |
| * |
| * @param x |
| * The X coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param y |
| * The Y coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param surface |
| * A Cairo surface containing the image data to be streamed. |
| */ |
| void guac_client_stream_png(guac_client* client, guac_socket* socket, |
| guac_composite_mode mode, const guac_layer* layer, int x, int y, |
| cairo_surface_t* surface); |
| |
| /** |
| * Streams the image data of the given surface over an image stream ("img" |
| * instruction) as JPEG-encoded data at the given quality. The image stream |
| * will be automatically allocated and freed. |
| * |
| * @param client |
| * The Guacamole client for which the image stream should be allocated. |
| * |
| * @param socket |
| * The socket over which instructions associated with the image stream |
| * should be sent. |
| * |
| * @param mode |
| * The composite mode to use when rendering the image over the given layer. |
| * |
| * @param layer |
| * The destination layer. |
| * |
| * @param x |
| * The X coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param y |
| * The Y coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param surface |
| * A Cairo surface containing the image data to be streamed. |
| * |
| * @param quality |
| * The JPEG image quality, which must be an integer value between 0 and 100 |
| * inclusive. Larger values indicate improving quality at the expense of |
| * larger file size. |
| */ |
| void guac_client_stream_jpeg(guac_client* client, guac_socket* socket, |
| guac_composite_mode mode, const guac_layer* layer, int x, int y, |
| cairo_surface_t* surface, int quality); |
| |
| /** |
| * Streams the image data of the given surface over an image stream ("img" |
| * instruction) as WebP-encoded data at the given quality. The image stream |
| * will be automatically allocated and freed. If the server does not support |
| * WebP, this function has no effect, so be sure to check the result of |
| * guac_client_supports_webp() prior to calling this function. |
| * |
| * @param client |
| * The Guacamole client for whom the image stream should be allocated. |
| * |
| * @param socket |
| * The socket over which instructions associated with the image stream |
| * should be sent. |
| * |
| * @param mode |
| * The composite mode to use when rendering the image over the given layer. |
| * |
| * @param layer |
| * The destination layer. |
| * |
| * @param x |
| * The X coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param y |
| * The Y coordinate of the upper-left corner of the destination rectangle |
| * within the given layer. |
| * |
| * @param surface |
| * A Cairo surface containing the image data to be streamed. |
| * |
| * @param quality |
| * The WebP image quality, which must be an integer value between 0 and 100 |
| * inclusive. For lossy images, larger values indicate improving quality at |
| * the expense of larger file size. For lossless images, this dictates the |
| * quality of compression, with larger values producing smaller files at |
| * the expense of speed. |
| * |
| * @param lossless |
| * Zero to encode a lossy image, non-zero to encode losslessly. |
| */ |
| void guac_client_stream_webp(guac_client* client, guac_socket* socket, |
| guac_composite_mode mode, const guac_layer* layer, int x, int y, |
| cairo_surface_t* surface, int quality, int lossless); |
| |
| /** |
| * Returns whether all users of the given client support WebP. If any user does |
| * not support WebP, or the server cannot encode WebP images, zero is returned. |
| * |
| * @param client |
| * The Guacamole client whose users should be checked for WebP support. |
| * |
| * @return |
| * Non-zero if the all users of the given client claim to support WebP and |
| * the server has been built with WebP support, zero otherwise. |
| */ |
| int guac_client_supports_webp(guac_client* client); |
| |
| /** |
| * The default Guacamole client layer, layer 0. |
| */ |
| extern const guac_layer* GUAC_DEFAULT_LAYER; |
| |
| #endif |
| |