cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

client.c (6041B)


      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#include "config.h"
     21
     22#include "client.h"
     23#include "user.h"
     24#include "vnc.h"
     25
     26#ifdef ENABLE_COMMON_SSH
     27#include "common-ssh/sftp.h"
     28#include "common-ssh/ssh.h"
     29#include "common-ssh/user.h"
     30#endif
     31
     32#ifdef ENABLE_PULSE
     33#include "pulse/pulse.h"
     34#endif
     35
     36#include <guacamole/client.h>
     37#include <guacamole/mem.h>
     38#include <guacamole/recording.h>
     39
     40#include <pthread.h>
     41#include <stdlib.h>
     42#include <string.h>
     43
     44#ifdef ENABLE_PULSE
     45/**
     46 * Add the provided user to the provided audio stream.
     47 *
     48 * @param user
     49 *    The pending user who should be added to the audio stream.
     50 *
     51 * @param data
     52 *    The audio stream that the user should be added to.
     53 *
     54 * @return
     55 *     Always NULL.
     56 */
     57static void* guac_vnc_sync_pending_user_audio(guac_user* user, void* data) {
     58
     59    /* Add the user to the stream */
     60    guac_pa_stream* audio = (guac_pa_stream*) data;
     61    guac_pa_stream_add_user(audio, user);
     62
     63    return NULL;
     64
     65}
     66#endif
     67
     68/**
     69 * A pending join handler implementation that will synchronize the connection
     70 * state for all pending users prior to them being promoted to full user.
     71 *
     72 * @param client
     73 *     The client whose pending users are about to be promoted.
     74 *
     75 * @return
     76 *     Always zero.
     77 */
     78static int guac_vnc_join_pending_handler(guac_client* client) {
     79
     80    guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
     81    guac_socket* broadcast_socket = client->pending_socket;
     82
     83#ifdef ENABLE_PULSE
     84    /* Synchronize any audio stream for each pending user */
     85    if (vnc_client->audio)
     86        guac_client_foreach_pending_user(
     87            client, guac_vnc_sync_pending_user_audio, vnc_client->audio);
     88#endif
     89
     90    /* Synchronize with current display */
     91    if (vnc_client->display != NULL) {
     92        guac_common_display_dup(vnc_client->display, client, broadcast_socket);
     93        guac_socket_flush(broadcast_socket);
     94    }
     95
     96    return 0;
     97
     98}
     99
    100int guac_client_init(guac_client* client) {
    101
    102    /* Set client args */
    103    client->args = GUAC_VNC_CLIENT_ARGS;
    104
    105    /* Alloc client data */
    106    guac_vnc_client* vnc_client = guac_mem_zalloc(sizeof(guac_vnc_client));
    107    client->data = vnc_client;
    108
    109#ifdef ENABLE_VNC_TLS_LOCKING
    110    /* Initialize the TLS write lock */
    111    pthread_mutex_init(&vnc_client->tls_lock, NULL);
    112#endif
    113
    114    /* Init clipboard */
    115    vnc_client->clipboard = guac_common_clipboard_alloc();
    116
    117    /* Set handlers */
    118    client->join_handler = guac_vnc_user_join_handler;
    119    client->join_pending_handler = guac_vnc_join_pending_handler;
    120    client->leave_handler = guac_vnc_user_leave_handler;
    121    client->free_handler = guac_vnc_client_free_handler;
    122
    123    return 0;
    124}
    125
    126int guac_vnc_client_free_handler(guac_client* client) {
    127
    128    guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
    129    guac_vnc_settings* settings = vnc_client->settings;
    130
    131    /* Clean up VNC client*/
    132    rfbClient* rfb_client = vnc_client->rfb_client;
    133    if (rfb_client != NULL) {
    134
    135        /* Wait for client thread to finish */
    136        pthread_join(vnc_client->client_thread, NULL);
    137
    138        /* Free memory that may not be free'd by libvncclient's
    139         * rfbClientCleanup() prior to libvncclient 0.9.12 */
    140
    141        if (rfb_client->frameBuffer != NULL) {
    142            free(rfb_client->frameBuffer);
    143            rfb_client->frameBuffer = NULL;
    144        }
    145
    146        if (rfb_client->raw_buffer != NULL) {
    147            free(rfb_client->raw_buffer);
    148            rfb_client->raw_buffer = NULL;
    149        }
    150
    151        if (rfb_client->rcSource != NULL) {
    152            free(rfb_client->rcSource);
    153            rfb_client->rcSource = NULL;
    154        }
    155
    156        /* Free VNC rfbClientData linked list (may not be free'd by
    157         * rfbClientCleanup(), depending on libvncclient version) */
    158
    159        while (rfb_client->clientData != NULL) {
    160            rfbClientData* next = rfb_client->clientData->next;
    161            free(rfb_client->clientData);
    162            rfb_client->clientData = next;
    163        }
    164
    165        rfbClientCleanup(rfb_client);
    166
    167    }
    168
    169#ifdef ENABLE_COMMON_SSH
    170    /* Free SFTP filesystem, if loaded */
    171    if (vnc_client->sftp_filesystem)
    172        guac_common_ssh_destroy_sftp_filesystem(vnc_client->sftp_filesystem);
    173
    174    /* Free SFTP session */
    175    if (vnc_client->sftp_session)
    176        guac_common_ssh_destroy_session(vnc_client->sftp_session);
    177
    178    /* Free SFTP user */
    179    if (vnc_client->sftp_user)
    180        guac_common_ssh_destroy_user(vnc_client->sftp_user);
    181
    182    guac_common_ssh_uninit();
    183#endif
    184
    185    /* Clean up recording, if in progress */
    186    if (vnc_client->recording != NULL)
    187        guac_recording_free(vnc_client->recording);
    188
    189    /* Free clipboard */
    190    if (vnc_client->clipboard != NULL)
    191        guac_common_clipboard_free(vnc_client->clipboard);
    192
    193    /* Free display */
    194    if (vnc_client->display != NULL)
    195        guac_common_display_free(vnc_client->display);
    196
    197#ifdef ENABLE_PULSE
    198    /* If audio enabled, stop streaming */
    199    if (vnc_client->audio)
    200        guac_pa_stream_free(vnc_client->audio);
    201#endif
    202
    203    /* Free parsed settings */
    204    if (settings != NULL)
    205        guac_vnc_settings_free(settings);
    206
    207#ifdef ENABLE_VNC_TLS_LOCKING
    208    /* Clean up TLS lock mutex. */
    209    pthread_mutex_destroy(&(vnc_client->tls_lock));
    210#endif
    211
    212    /* Free generic data struct */
    213    guac_mem_free(client->data);
    214
    215    return 0;
    216}
    217