cscg24-guacamole

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

channels.c (4946B)


      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 "plugins/channels.h"
     21#include "rdp.h"
     22
     23#include <freerdp/channels/channels.h>
     24#include <freerdp/freerdp.h>
     25#include <freerdp/addin.h>
     26#include <guacamole/mem.h>
     27#include <winpr/wtypes.h>
     28
     29#include <stdarg.h>
     30#include <stdlib.h>
     31#include <string.h>
     32
     33int guac_rdp_wrapped_entry_ex_count = 0;
     34
     35int guac_rdp_wrapped_entry_count = 0;
     36
     37PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
     38
     39PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
     40
     41PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client,
     42        PVIRTUALCHANNELENTRYEX entry_ex) {
     43
     44    /* Do not wrap if there is insufficient space to store the wrapped
     45     * function */
     46    if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) {
     47        guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static "
     48                "channels has been reached. Further FreeRDP plugins and "
     49                "channel support may fail to load.");
     50        return entry_ex;
     51    }
     52
     53    /* Generate wrapped version of provided entry point */
     54    PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
     55    guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
     56    guac_rdp_wrapped_entry_ex_count++;
     57
     58    return wrapper;
     59
     60}
     61
     62PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client,
     63        PVIRTUALCHANNELENTRY entry) {
     64
     65    /* Do not wrap if there is insufficient space to store the wrapped
     66     * function */
     67    if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) {
     68        guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static "
     69                "channels has been reached. Further FreeRDP plugins and "
     70                "channel support may fail to load.");
     71        return entry;
     72    }
     73
     74    /* Generate wrapped version of provided entry point */
     75    PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count];
     76    guac_rdp_wrapped_entry[guac_rdp_wrapped_entry_count] = entry;
     77    guac_rdp_wrapped_entry_count++;
     78
     79    return wrapper;
     80
     81}
     82
     83int guac_freerdp_channels_load_plugin(rdpContext* context,
     84        const char* name, void* data) {
     85
     86    guac_client* client = ((rdp_freerdp_context*) context)->client;
     87
     88    /* Load plugin using "ex" version of the channel plugin entry point, if it exists */
     89    PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name,
     90            NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX);
     91
     92    if (entry_ex != NULL) {
     93        entry_ex = guac_rdp_plugin_wrap_entry_ex(client, entry_ex);
     94        return freerdp_channels_client_load_ex(context->channels, context->settings, entry_ex, data);
     95    }
     96
     97    /* Lacking the "ex" entry point, attempt to load using the non-ex version */
     98    PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name,
     99            NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
    100
    101    if (entry != NULL) {
    102        entry = guac_rdp_plugin_wrap_entry(client, entry);
    103        return freerdp_channels_client_load(context->channels, context->settings, entry, data);
    104    }
    105
    106    /* The plugin does not exist / cannot be loaded */
    107    return 1;
    108
    109}
    110
    111void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings,
    112        const char* name, ...) {
    113
    114    va_list args;
    115
    116    ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV));
    117
    118    va_start(args, name);
    119
    120    /* Count number of arguments (excluding terminating NULL) */
    121    freerdp_args->argc = 1;
    122    while (va_arg(args, char*) != NULL)
    123        freerdp_args->argc++;
    124
    125    /* Reset va_list */
    126    va_end(args);
    127    va_start(args, name);
    128
    129    /* Copy argument values into DVC entry */
    130    freerdp_args->argv = malloc(guac_mem_ckd_mul_or_die(sizeof(char*), freerdp_args->argc));
    131    freerdp_args->argv[0] = strdup(name);
    132    int i;
    133    for (i = 1; i < freerdp_args->argc; i++)
    134        freerdp_args->argv[i] = strdup(va_arg(args, char*));
    135
    136    va_end(args);
    137
    138    /* Register plugin with FreeRDP */
    139    settings->SupportDynamicChannels = TRUE;
    140    freerdp_dynamic_channel_collection_add(settings, freerdp_args);
    141
    142}
    143