blob: 71d48f22a4b9ca60e197ba72e73fe24e43309ff9 [file] [log] [blame]
/*
* 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, or NULL if the
* maximum number of active streams has been reached.
*/
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