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