1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef _GUAC_CLIENT_H
21 #define _GUAC_CLIENT_H
22 
23 /**
24  * Functions and structure contents for the Guacamole proxy client.
25  *
26  * @file client.h
27  */
28 
29 #include "client-fntypes.h"
30 #include "client-types.h"
31 #include "client-constants.h"
32 #include "layer-types.h"
33 #include "object-types.h"
34 #include "pool-types.h"
35 #include "socket-types.h"
36 #include "stream-types.h"
37 #include "timestamp-types.h"
38 #include "user-fntypes.h"
39 #include "user-types.h"
40 
41 #include <cairo/cairo.h>
42 
43 #include <pthread.h>
44 #include <stdarg.h>
45 
46 struct guac_client {
47 
48     /**
49      * The guac_socket structure to be used to communicate with all connected
50      * web-clients (users). Unlike the user-level guac_socket, this guac_socket
51      * will broadcast instructions to all connected users simultaneously.  It
52      * is expected that the implementor of any Guacamole proxy client will
53      * provide their own mechanism of I/O for their protocol. The guac_socket
54      * structure is used only to communicate conveniently with the Guacamole
55      * web-client.
56      */
57     guac_socket* socket;
58 
59     /**
60      * The current state of the client. When the client is first allocated,
61      * this will be initialized to GUAC_CLIENT_RUNNING. It will remain at
62      * GUAC_CLIENT_RUNNING until an event occurs which requires the client to
63      * shutdown, at which point the state becomes GUAC_CLIENT_STOPPING.
64      */
65     guac_client_state state;
66 
67     /**
68      * Arbitrary reference to proxy client-specific data. Implementors of a
69      * Guacamole proxy client can store any data they want here, which can then
70      * be retrieved as necessary in the message handlers.
71      */
72     void* data;
73 
74     /**
75      * The time (in milliseconds) that the last sync message was sent to the
76      * client.
77      */
78     guac_timestamp last_sent_timestamp;
79 
80     /**
81      * Handler for freeing data when the client is being unloaded.
82      *
83      * This handler will be called when the client needs to be unloaded
84      * by the proxy, and any data allocated by the proxy client should be
85      * freed.
86      *
87      * Note that this handler will NOT be called if the client's
88      * guac_client_init() function fails.
89      *
90      * Implement this handler if you store data inside the client.
91      *
92      * Example:
93      * @code
94      *     int free_handler(guac_client* client);
95      *
96      *     int guac_client_init(guac_client* client) {
97      *         client->free_handler = free_handler;
98      *     }
99      * @endcode
100      */
101     guac_client_free_handler* free_handler;
102 
103     /**
104      * Logging handler. This handler will be called via guac_client_log() when
105      * the client needs to log messages of any type.
106      *
107      * In general, only programs loading the client should implement this
108      * handler, as those are the programs that would provide the logging
109      * facilities.
110      *
111      * Client implementations should expect these handlers to already be
112      * set.
113      *
114      * Example:
115      * @code
116      *     void log_handler(guac_client* client, guac_client_log_level level, const char* format, va_list args);
117      *
118      *     void function_of_daemon() {
119      *
120      *         guac_client* client = [pass log_handler to guac_client_plugin_get_client()];
121      *
122      *     }
123      * @endcode
124      */
125     guac_client_log_handler* log_handler;
126 
127     /**
128      * Pool of buffer indices. Buffers are simply layers with negative indices.
129      * Note that because guac_pool always gives non-negative indices starting
130      * at 0, the output of this guac_pool will be adjusted.
131      */
132     guac_pool* __buffer_pool;
133 
134     /**
135      * Pool of layer indices. Note that because guac_pool always gives
136      * non-negative indices starting at 0, the output of this guac_pool will
137      * be adjusted.
138      */
139     guac_pool* __layer_pool;
140 
141     /**
142      * Pool of stream indices.
143      */
144     guac_pool* __stream_pool;
145 
146     /**
147      * All available client-level output streams (data going to all connected
148      * users).
149      */
150     guac_stream* __output_streams;
151 
152     /**
153      * The unique identifier allocated for the connection, which may
154      * be used within the Guacamole protocol to refer to this connection.
155      * This identifier is guaranteed to be unique from all existing
156      * connections and will not collide with any available protocol
157      * names.
158      */
159     char* connection_id;
160 
161     /**
162      * Lock which is acquired when the users list is being manipulated, or when
163      * the users list is being iterated.
164      */
165     pthread_rwlock_t __users_lock;
166 
167     /**
168      * The first user within the list of all connected users, or NULL if no
169      * users are currently connected.
170      */
171     guac_user* __users;
172 
173     /**
174      * The user that first created this connection. This user will also have
175      * their "owner" flag set to a non-zero value. If the owner has left the
176      * connection, this will be NULL.
177      */
178     guac_user* __owner;
179 
180     /**
181      * The number of currently-connected users. This value may include inactive
182      * users if cleanup of those users has not yet finished.
183      */
184     int connected_users;
185 
186     /**
187      * Handler for join events, called whenever a new user is joining an active
188      * connection. Note that because users may leave the connection at any
189      * time, a reference to a guac_user can become invalid at any time and
190      * should never be maintained outside the scope of a function invoked by
191      * libguac to which that guac_user was passed (the scope in which the
192      * guac_user reference is guaranteed to be valid) UNLESS that reference is
193      * properly invalidated within the leave_handler.
194      *
195      * The handler is given a pointer to a newly-allocated guac_user which
196      * must then be initialized, if needed.
197      *
198      * Example:
199      * @code
200      *     int join_handler(guac_user* user, int argc, char** argv);
201      *
202      *     int guac_client_init(guac_client* client) {
203      *         client->join_handler = join_handler;
204      *     }
205      * @endcode
206      */
207     guac_user_join_handler* join_handler;
208 
209     /**
210      * Handler for leave events, called whenever a new user is leaving an
211      * active connection.
212      *
213      * The handler is given a pointer to the leaving guac_user whose custom
214      * data and associated resources must now be freed, if any.
215      *
216      * Example:
217      * @code
218      *     int leave_handler(guac_user* user);
219      *
220      *     int guac_client_init(guac_client* client) {
221      *         client->leave_handler = leave_handler;
222      *     }
223      * @endcode
224      */
225     guac_user_leave_handler* leave_handler;
226 
227     /**
228      * NULL-terminated array of all arguments accepted by this client , in
229      * order. New users will specify these arguments when they join the
230      * connection, and the values of those arguments will be made available to
231      * the function initializing newly-joined users.
232      *
233      * The guac_client_init entry point is expected to initialize this, if
234      * arguments are expected.
235      *
236      * Example:
237      * @code
238      *     const char* __my_args[] = {
239      *         "hostname",
240      *         "port",
241      *         "username",
242      *         "password",
243      *         NULL
244      *     };
245      *
246      *     int guac_client_init(guac_client* client) {
247      *         client->args = __my_args;
248      *     }
249      * @endcode
250      */
251     const char** args;
252 
253     /**
254      * Handle to the dlopen()'d plugin, which should be given to dlclose() when
255      * this client is freed. This is only assigned if guac_client_load_plugin()
256      * is used.
257      */
258     void* __plugin_handle;
259 
260 };
261 
262 /**
263  * Returns a new, barebones guac_client. This new guac_client has no handlers
264  * set, but is otherwise usable.
265  *
266  * @return A pointer to the new client.
267  */
268 guac_client* guac_client_alloc();
269 
270 /**
271  * Free all resources associated with the given client.
272  *
273  * @param client The proxy client to free all reasources of.
274  */
275 void guac_client_free(guac_client* client);
276 
277 /**
278  * Writes a message in the log used by the given client. The logger used will
279  * normally be defined by guacd (or whichever program loads the proxy client)
280  * by setting the logging handlers of the client when it is loaded.
281  *
282  * @param client The proxy client logging this message.
283  * @param level The level at which to log this message.
284  * @param format A printf-style format string to log.
285  * @param ... Arguments to use when filling the format string for printing.
286  */
287 void guac_client_log(guac_client* client, guac_client_log_level level,
288         const char* format, ...);
289 
290 /**
291  * Writes a message in the log used by the given client. The logger used will
292  * normally be defined by guacd (or whichever program loads the proxy client)
293  * by setting the logging handlers of the client when it is loaded.
294  *
295  * @param client The proxy client logging this message.
296  * @param level The level at which to log this message.
297  * @param format A printf-style format string to log.
298  * @param ap The va_list containing the arguments to be used when filling the
299  *           format string for printing.
300  */
301 void vguac_client_log(guac_client* client, guac_client_log_level level,
302         const char* format, va_list ap);
303 
304 /**
305  * Signals the given client to stop gracefully. This is a completely
306  * cooperative signal, and can be ignored by the client or the hosting
307  * daemon.
308  *
309  * @param client The proxy client to signal to stop.
310  */
311 void guac_client_stop(guac_client* client);
312 
313 /**
314  * Signals the given client to stop gracefully, while also signalling via the
315  * Guacamole protocol that an error has occurred. Note that this is a completely
316  * cooperative signal, and can be ignored by the client or the hosting
317  * daemon. The message given will be logged to the system logs.
318  *
319  * @param client The proxy client to signal to stop.
320  * @param status The status to send over the Guacamole protocol.
321  * @param format A printf-style format string to log.
322  * @param ... Arguments to use when filling the format string for printing.
323  */
324 void guac_client_abort(guac_client* client, guac_protocol_status status,
325         const char* format, ...);
326 
327 /**
328  * Signals the given client to stop gracefully, while also signalling via the
329  * Guacamole protocol that an error has occurred. Note that this is a completely
330  * cooperative signal, and can be ignored by the client or the hosting
331  * daemon. The message given will be logged to the system logs.
332  *
333  * @param client The proxy client to signal to stop.
334  * @param status The status to send over the Guacamole protocol.
335  * @param format A printf-style format string to log.
336  * @param ap The va_list containing the arguments to be used when filling the
337  *           format string for printing.
338  */
339 void vguac_client_abort(guac_client* client, guac_protocol_status status,
340         const char* format, va_list ap);
341 
342 /**
343  * Allocates a new buffer (invisible layer). An arbitrary index is
344  * automatically assigned if no existing buffer is available for use.
345  *
346  * @param client The proxy client to allocate the buffer for.
347  * @return The next available buffer, or a newly allocated buffer.
348  */
349 guac_layer* guac_client_alloc_buffer(guac_client* client);
350 
351 /**
352  * Allocates a new layer. An arbitrary index is automatically assigned
353  * if no existing layer is available for use.
354  *
355  * @param client The proxy client to allocate the layer buffer for.
356  * @return The next available layer, or a newly allocated layer.
357  */
358 guac_layer* guac_client_alloc_layer(guac_client* client);
359 
360 /**
361  * Returns the given buffer to the pool of available buffers, such that it
362  * can be reused by any subsequent call to guac_client_allow_buffer().
363  *
364  * @param client The proxy client to return the buffer to.
365  * @param layer The buffer to return to the pool of available buffers.
366  */
367 void guac_client_free_buffer(guac_client* client, guac_layer* layer);
368 
369 /**
370  * Returns the given layer to the pool of available layers, such that it
371  * can be reused by any subsequent call to guac_client_allow_layer().
372  *
373  * @param client The proxy client to return the layer to.
374  * @param layer The buffer to return to the pool of available layer.
375  */
376 void guac_client_free_layer(guac_client* client, guac_layer* layer);
377 
378 /**
379  * Allocates a new stream. An arbitrary index is automatically assigned
380  * if no previously-allocated stream is available for use.
381  *
382  * @param client
383  *     The client to allocate the stream for.
384  *
385  * @return
386  *     The next available stream, or a newly allocated stream, or NULL if the
387  *     maximum number of active streams has been reached.
388  */
389 guac_stream* guac_client_alloc_stream(guac_client* client);
390 
391 /**
392  * Returns the given stream to the pool of available streams, such that it
393  * can be reused by any subsequent call to guac_client_alloc_stream().
394  *
395  * @param client
396  *     The client to return the stream to.
397  *
398  * @param stream
399  *     The stream to return to the pool of available stream.
400  */
401 void guac_client_free_stream(guac_client* client, guac_stream* stream);
402 
403 /**
404  * Adds the given user to the internal list of connected users. Future writes
405  * to the broadcast socket stored within guac_client will also write to this
406  * user. The join handler of this guac_client will be called.
407  *
408  * @param client The proxy client to add the user to.
409  * @param user The user to add.
410  * @param argc The number of arguments to pass to the new user.
411  * @param argv An array of strings containing the argument values being passed.
412  * @return Zero if the user was added successfully, non-zero if the user could
413  *         not join the connection.
414  */
415 int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** argv);
416 
417 /**
418  * Removes the given user, removing the user from the internally-tracked list
419  * of connected users, and calling any appropriate leave handler.
420  *
421  * @param client The proxy client to return the buffer to.
422  * @param user The user to remove.
423  */
424 void guac_client_remove_user(guac_client* client, guac_user* user);
425 
426 /**
427  * Calls the given function on all currently-connected users of the given
428  * client. The function will be given a reference to a guac_user and the
429  * specified arbitrary data. The value returned by the callback will be
430  * ignored.
431  *
432  * This function is reentrant, but the user list MUST NOT be manipulated
433  * within the same thread as a callback to this function. Though the callback
434  * MAY invoke guac_client_foreach_user(), doing so should not be necessary, and
435  * may indicate poor design choices.
436  *
437  * @param client
438  *     The client whose users should be iterated.
439  *
440  * @param callback
441  *     The function to call for each user.
442  *
443  * @param data
444  *     Arbitrary data to pass to the callback each time it is invoked.
445  */
446 void guac_client_foreach_user(guac_client* client,
447         guac_user_callback* callback, void* data);
448 
449 /**
450  * Calls the given function with the currently-connected user that is marked as
451  * the owner. The owner of a connection is the user that established the
452  * initial connection that created the connection (the first user to connect
453  * and join). The function will be given a reference to the guac_user and the
454  * specified arbitrary data. If the owner has since left the connection, the
455  * function will instead be invoked with NULL as the guac_user. The value
456  * returned by the callback will be returned by this function.
457  *
458  * This function is reentrant, but the user list MUST NOT be manipulated
459  * within the same thread as a callback to this function.
460  *
461  * @param client
462  *     The client to retrieve the owner from.
463  *
464  * @param callback
465  *     The callback to invoke on the user marked as the owner of the
466  *     connection. NULL will be passed to this callback instead if there is no
467  *     owner.
468  *
469  * @param data
470  *     Arbitrary data to pass to the given callback.
471  *
472  * @return
473  *     The value returned by the callback.
474  */
475 void* guac_client_for_owner(guac_client* client, guac_user_callback* callback,
476         void* data);
477 
478 /**
479  * Calls the given function with the given user ONLY if they are currently
480  * connected. The function will be given a reference to the guac_user and the
481  * specified arbitrary data. If the provided user doesn't exist or has since
482  * left the connection, the function will instead be invoked with NULL as the
483  * guac_user. The value returned by the callback will be returned by this
484  * function.
485  *
486  * This function is reentrant, but the user list MUST NOT be manipulated
487  * within the same thread as a callback to this function.
488  *
489  * @param client
490  *     The client that the given user is expected to be associated with.
491  *
492  * @param user
493  *     The user to provide to the given callback if valid. The pointer need not
494  *     even point to properly allocated memory; the user will only be passed to
495  *     the callback function if they are valid, and the provided user pointer
496  *     will not be dereferenced during this process.
497  *
498  * @param callback
499  *     The callback to invoke on the given user if they are valid. NULL will be
500  *     passed to this callback instead if the user is not valid.
501  *
502  * @param data
503  *     Arbitrary data to pass to the given callback.
504  *
505  * @return
506  *     The value returned by the callback.
507  */
508 void* guac_client_for_user(guac_client* client, guac_user* user,
509         guac_user_callback* callback, void* data);
510 
511 /**
512  * Marks the end of the current frame by sending a "sync" instruction to
513  * all connected users. This instruction will contain the current timestamp.
514  * The last_sent_timestamp member of guac_client will be updated accordingly.
515  *
516  * If an error occurs sending the instruction, a non-zero value is
517  * returned, and guac_error is set appropriately.
518  *
519  * @param client The guac_client which has finished a frame.
520  * @return Zero on success, non-zero on error.
521  */
522 int guac_client_end_frame(guac_client* client);
523 
524 /**
525  * Initializes the given guac_client using the initialization routine provided
526  * by the plugin corresponding to the named protocol. This will automatically
527  * invoke guac_client_init within the plugin for the given protocol.
528  *
529  * Note that the connection will likely not be established until the first
530  * user (the "owner") is added to the client.
531  *
532  * @param client The guac_client to initialize.
533  * @param protocol The name of the protocol to use.
534  * @return Zero if initialization was successful, non-zero otherwise.
535  */
536 int guac_client_load_plugin(guac_client* client, const char* protocol);
537 
538 /**
539  * Calculates and returns the approximate processing lag experienced by the
540  * pool of users. The processing lag is the difference in time between server
541  * and client due purely to data processing and excluding network delays.
542  *
543  * @param client
544  *     The guac_client to calculate the processing lag of.
545  *
546  * @return
547  *     The approximate processing lag of the pool of users associated with the
548  *     given guac_client, in milliseconds.
549  */
550 int guac_client_get_processing_lag(guac_client* client);
551 
552 /**
553  * Sends a request to the owner of the given guac_client for parameters required
554  * to continue the connection started by the client. The function returns zero
555  * on success or non-zero on failure.
556  *
557  * @param client
558  *     The client where additional connection parameters are required.
559  *
560  * @param required
561  *     The NULL-terminated array of required parameters.
562  *
563  * @return
564  *     Zero on success, non-zero on failure.
565  */
566 int guac_client_owner_send_required(guac_client* client, const char** required);
567 
568 /**
569  * Streams the given connection parameter value over an argument value stream
570  * ("argv" instruction), exposing the current value of the named connection
571  * parameter to all users of the given client. The argument value stream will
572  * be automatically allocated and freed.
573  *
574  * @param client
575  *     The Guacamole client for which the argument value stream should be
576  *     allocated.
577  *
578  * @param socket
579  *     The socket over which instructions associated with the argument value
580  *     stream should be sent.
581  *
582  * @param mimetype
583  *     The mimetype of the data within the connection parameter value being
584  *     sent.
585  *
586  * @param name
587  *     The name of the connection parameter being sent.
588  *
589  * @param value
590  *     The current value of the connection parameter being sent.
591  */
592 void guac_client_stream_argv(guac_client* client, guac_socket* socket,
593         const char* mimetype, const char* name, const char* value);
594 
595 /**
596  * Streams the image data of the given surface over an image stream ("img"
597  * instruction) as PNG-encoded data. The image stream will be automatically
598  * allocated and freed.
599  *
600  * @param client
601  *     The Guacamole client for which the image stream should be allocated.
602  *
603  * @param socket
604  *     The socket over which instructions associated with the image stream
605  *     should be sent.
606  *
607  * @param mode
608  *     The composite mode to use when rendering the image over the given layer.
609  *
610  * @param layer
611  *     The destination layer.
612  *
613  * @param x
614  *     The X coordinate of the upper-left corner of the destination rectangle
615  *     within the given layer.
616  *
617  * @param y
618  *     The Y coordinate of the upper-left corner of the destination rectangle
619  *     within the given layer.
620  *
621  * @param surface
622  *     A Cairo surface containing the image data to be streamed.
623  */
624 void guac_client_stream_png(guac_client* client, guac_socket* socket,
625         guac_composite_mode mode, const guac_layer* layer, int x, int y,
626         cairo_surface_t* surface);
627 
628 /**
629  * Streams the image data of the given surface over an image stream ("img"
630  * instruction) as JPEG-encoded data at the given quality. The image stream
631  * will be automatically allocated and freed.
632  *
633  * @param client
634  *     The Guacamole client for which the image stream should be allocated.
635  *
636  * @param socket
637  *     The socket over which instructions associated with the image stream
638  *     should be sent.
639  *
640  * @param mode
641  *     The composite mode to use when rendering the image over the given layer.
642  *
643  * @param layer
644  *     The destination layer.
645  *
646  * @param x
647  *     The X coordinate of the upper-left corner of the destination rectangle
648  *     within the given layer.
649  *
650  * @param y
651  *     The Y coordinate of the upper-left corner of the destination rectangle
652  *     within the given layer.
653  *
654  * @param surface
655  *     A Cairo surface containing the image data to be streamed.
656  *
657  * @param quality
658  *     The JPEG image quality, which must be an integer value between 0 and 100
659  *     inclusive. Larger values indicate improving quality at the expense of
660  *     larger file size.
661  */
662 void guac_client_stream_jpeg(guac_client* client, guac_socket* socket,
663         guac_composite_mode mode, const guac_layer* layer, int x, int y,
664         cairo_surface_t* surface, int quality);
665 
666 /**
667  * Streams the image data of the given surface over an image stream ("img"
668  * instruction) as WebP-encoded data at the given quality. The image stream
669  * will be automatically allocated and freed. If the server does not support
670  * WebP, this function has no effect, so be sure to check the result of
671  * guac_client_supports_webp() prior to calling this function.
672  *
673  * @param client
674  *     The Guacamole client for whom the image stream should be allocated.
675  *
676  * @param socket
677  *     The socket over which instructions associated with the image stream
678  *     should be sent.
679  *
680  * @param mode
681  *     The composite mode to use when rendering the image over the given layer.
682  *
683  * @param layer
684  *     The destination layer.
685  *
686  * @param x
687  *     The X coordinate of the upper-left corner of the destination rectangle
688  *     within the given layer.
689  *
690  * @param y
691  *     The Y coordinate of the upper-left corner of the destination rectangle
692  *     within the given layer.
693  *
694  * @param surface
695  *     A Cairo surface containing the image data to be streamed.
696  *
697  * @param quality
698  *     The WebP image quality, which must be an integer value between 0 and 100
699  *     inclusive. For lossy images, larger values indicate improving quality at
700  *     the expense of larger file size. For lossless images, this dictates the
701  *     quality of compression, with larger values producing smaller files at
702  *     the expense of speed.
703  *
704  * @param lossless
705  *     Zero to encode a lossy image, non-zero to encode losslessly.
706  */
707 void guac_client_stream_webp(guac_client* client, guac_socket* socket,
708         guac_composite_mode mode, const guac_layer* layer, int x, int y,
709         cairo_surface_t* surface, int quality, int lossless);
710 
711 /**
712  * Returns whether the owner of the given client supports the "required"
713  * instruction, returning non-zero if the client owner does support the
714  * instruction, or zero if the owner does not.
715  *
716  * @param client
717  *     The Guacamole client whose owner should be checked for supporting
718  *     the "required" instruction.
719  *
720  * @return
721  *     Non-zero if the owner of the given client supports the "required"
722  *     instruction, zero otherwise.
723  */
724 int guac_client_owner_supports_required(guac_client* client);
725 
726 /**
727  * Returns whether all users of the given client support WebP. If any user does
728  * not support WebP, or the server cannot encode WebP images, zero is returned.
729  *
730  * @param client
731  *     The Guacamole client whose users should be checked for WebP support.
732  *
733  * @return
734  *     Non-zero if the all users of the given client claim to support WebP and
735  *     the server has been built with WebP support, zero otherwise.
736  */
737 int guac_client_supports_webp(guac_client* client);
738 
739 /**
740  * The default Guacamole client layer, layer 0.
741  */
742 extern const guac_layer* GUAC_DEFAULT_LAYER;
743 
744 #endif
745 
746