cscg24-guacamole

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

client.c (5606B)


      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 "argv.h"
     21#include "client.h"
     22#include "kubernetes.h"
     23#include "settings.h"
     24#include "user.h"
     25
     26#include <guacamole/argv.h>
     27#include <guacamole/client.h>
     28#include <guacamole/mem.h>
     29#include <guacamole/socket.h>
     30#include <libwebsockets.h>
     31
     32#include <langinfo.h>
     33#include <locale.h>
     34#include <pthread.h>
     35#include <stdlib.h>
     36#include <string.h>
     37
     38guac_client* guac_kubernetes_lws_current_client = NULL;
     39
     40/**
     41 * Logging callback invoked by libwebsockets to log a single line of logging
     42 * output. As libwebsockets messages are all generally low-level, the log
     43 * level provided by libwebsockets is ignored here, with all messages logged
     44 * instead at guacd's debug level.
     45 *
     46 * @param level
     47 *     The libwebsockets log level associated with the log message. This value
     48 *     is ignored by this implementation of the logging callback.
     49 *
     50 * @param line
     51 *     The line of logging output to log.
     52 */
     53static void guac_kubernetes_log(int level, const char* line) {
     54
     55    char buffer[1024];
     56
     57    /* Drop log message if there's nowhere to log yet */
     58    if (guac_kubernetes_lws_current_client == NULL)
     59        return;
     60
     61    /* Trim length of line to fit buffer (plus null terminator) */
     62    int length = strlen(line);
     63    if (length > sizeof(buffer) - 1)
     64        length = sizeof(buffer) - 1;
     65
     66    /* Copy as much of the received line as will fit in the buffer */
     67    memcpy(buffer, line, length);
     68
     69    /* If the line ends with a newline character, trim the character */
     70    if (length > 0 && buffer[length - 1] == '\n')
     71        length--;
     72
     73    /* Null-terminate the trimmed string */
     74    buffer[length] = '\0';
     75
     76    /* Log using guacd's own log facilities */
     77    guac_client_log(guac_kubernetes_lws_current_client, GUAC_LOG_DEBUG,
     78            "libwebsockets: %s", buffer);
     79
     80}
     81
     82/**
     83 * A pending join handler implementation that will synchronize the connection
     84 * state for all pending users prior to them being promoted to full user.
     85 *
     86 * @param client
     87 *     The client whose pending users are about to be promoted to full users,
     88 *     and therefore need their connection state synchronized.
     89 *
     90 * @return
     91 *     Always zero.
     92 */
     93static int guac_kubernetes_join_pending_handler(guac_client* client) {
     94
     95    guac_kubernetes_client* kubernetes_client =
     96        (guac_kubernetes_client*) client->data;
     97
     98    /* Synchronize the terminal state to all pending users */
     99    if (kubernetes_client->term != NULL) {
    100        guac_socket* broadcast_socket = client->pending_socket;
    101        guac_terminal_sync_users(kubernetes_client->term, client, broadcast_socket);
    102        guac_kubernetes_send_current_argv_batch(client, broadcast_socket);
    103        guac_socket_flush(broadcast_socket);
    104    }
    105
    106    return 0;
    107
    108}
    109
    110int guac_client_init(guac_client* client) {
    111
    112    /* Ensure reference to main guac_client remains available in all
    113     * libwebsockets contexts */
    114    guac_kubernetes_lws_current_client = client;
    115
    116    /* Redirect libwebsockets logging */
    117    lws_set_log_level(LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO,
    118            guac_kubernetes_log);
    119
    120    /* Set client args */
    121    client->args = GUAC_KUBERNETES_CLIENT_ARGS;
    122
    123    /* Allocate client instance data */
    124    guac_kubernetes_client* kubernetes_client = guac_mem_zalloc(sizeof(guac_kubernetes_client));
    125    client->data = kubernetes_client;
    126
    127    /* Set handlers */
    128    client->join_handler = guac_kubernetes_user_join_handler;
    129    client->join_pending_handler = guac_kubernetes_join_pending_handler;
    130    client->free_handler = guac_kubernetes_client_free_handler;
    131    client->leave_handler = guac_kubernetes_user_leave_handler;
    132
    133    /* Register handlers for argument values that may be sent after the handshake */
    134    guac_argv_register(GUAC_KUBERNETES_ARGV_COLOR_SCHEME, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
    135    guac_argv_register(GUAC_KUBERNETES_ARGV_FONT_NAME, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
    136    guac_argv_register(GUAC_KUBERNETES_ARGV_FONT_SIZE, guac_kubernetes_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
    137
    138    /* Set locale and warn if not UTF-8 */
    139    setlocale(LC_CTYPE, "");
    140    if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) {
    141        guac_client_log(client, GUAC_LOG_INFO,
    142                "Current locale does not use UTF-8. Some characters may "
    143                "not render correctly.");
    144    }
    145
    146    /* Success */
    147    return 0;
    148
    149}
    150
    151int guac_kubernetes_client_free_handler(guac_client* client) {
    152
    153    guac_kubernetes_client* kubernetes_client =
    154        (guac_kubernetes_client*) client->data;
    155
    156    /* Wait client thread to terminate */
    157    pthread_join(kubernetes_client->client_thread, NULL);
    158
    159    /* Free settings */
    160    if (kubernetes_client->settings != NULL)
    161        guac_kubernetes_settings_free(kubernetes_client->settings);
    162
    163    guac_mem_free(kubernetes_client);
    164    return 0;
    165
    166}
    167