cscg24-guacamole

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

io.c (4748B)


      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 "kubernetes.h"
     21#include "terminal/terminal.h"
     22
     23#include <guacamole/client.h>
     24#include <libwebsockets.h>
     25
     26#include <pthread.h>
     27#include <stdbool.h>
     28#include <string.h>
     29
     30void guac_kubernetes_receive_data(guac_client* client,
     31        const char* buffer, size_t length) {
     32
     33    guac_kubernetes_client* kubernetes_client =
     34        (guac_kubernetes_client*) client->data;
     35
     36    /* Strip channel index from beginning of buffer */
     37    int channel = *(buffer++);
     38    length--;
     39
     40    switch (channel) {
     41
     42        /* Write STDOUT / STDERR directly to terminal as output */
     43        case GUAC_KUBERNETES_CHANNEL_STDOUT:
     44        case GUAC_KUBERNETES_CHANNEL_STDERR:
     45            guac_terminal_write(kubernetes_client->term, buffer, length);
     46            break;
     47
     48        /* Ignore data on other channels */
     49        default:
     50            guac_client_log(client, GUAC_LOG_DEBUG, "Received %i bytes along "
     51                    "channel %i.", length, channel);
     52
     53    }
     54
     55}
     56
     57void guac_kubernetes_send_message(guac_client* client,
     58        int channel, const char* data, int length) {
     59
     60    guac_kubernetes_client* kubernetes_client =
     61        (guac_kubernetes_client*) client->data;
     62
     63    pthread_mutex_lock(&(kubernetes_client->outbound_message_lock));
     64
     65    /* Add message to buffer if space is available */
     66    if (kubernetes_client->outbound_messages_waiting
     67            < GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES) {
     68
     69        /* Calculate storage position of next message */
     70        int index = (kubernetes_client->outbound_messages_top
     71                  + kubernetes_client->outbound_messages_waiting)
     72                  % GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES;
     73
     74        /* Obtain pointer to message slot at calculated position */
     75        guac_kubernetes_message* message =
     76            &(kubernetes_client->outbound_messages[index]);
     77
     78        /* Copy details of message into buffer */
     79        message->channel = channel;
     80        memcpy(message->data, data, length);
     81        message->length = length;
     82
     83        /* One more message is now waiting */
     84        kubernetes_client->outbound_messages_waiting++;
     85
     86        /* Notify libwebsockets that we need a callback to send pending
     87         * messages */
     88        lws_callback_on_writable(kubernetes_client->wsi);
     89        lws_cancel_service(kubernetes_client->context);
     90
     91    }
     92
     93    /* Warn if data has to be dropped */
     94    else
     95        guac_client_log(client, GUAC_LOG_WARNING, "Send buffer could not be "
     96                "flushed in time to handle additional data. Outbound "
     97                "message dropped.");
     98
     99    pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock));
    100
    101}
    102
    103bool guac_kubernetes_write_pending_message(guac_client* client) {
    104
    105    bool messages_remain;
    106    guac_kubernetes_client* kubernetes_client =
    107        (guac_kubernetes_client*) client->data;
    108
    109    pthread_mutex_lock(&(kubernetes_client->outbound_message_lock));
    110
    111    /* Send one message from top of buffer */
    112    if (kubernetes_client->outbound_messages_waiting > 0) {
    113
    114        /* Obtain pointer to message at top */
    115        int top = kubernetes_client->outbound_messages_top;
    116        guac_kubernetes_message* message =
    117            &(kubernetes_client->outbound_messages[top]);
    118
    119        /* Write message including channel index */
    120        lws_write(kubernetes_client->wsi,
    121                ((unsigned char*) message) + LWS_PRE,
    122                message->length + 1, LWS_WRITE_BINARY);
    123
    124        /* Advance top to next message */
    125        kubernetes_client->outbound_messages_top++;
    126        kubernetes_client->outbound_messages_top %=
    127            GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES;
    128
    129        /* One less message is waiting */
    130        kubernetes_client->outbound_messages_waiting--;
    131
    132    }
    133
    134    /* Record whether messages remained at time of completion */
    135    messages_remain = (kubernetes_client->outbound_messages_waiting > 0);
    136
    137    pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock));
    138
    139    return messages_remain;
    140
    141}
    142
    143