コード例 #1
0
ファイル: display.c プロジェクト: tamx/guacamole-server
void guac_terminal_display_dup(guac_terminal_display* display, guac_user* user,
        guac_socket* socket) {

    /* Create default surface */
    guac_common_surface_dup(display->display_surface, user, socket);

    /* Select layer is a child of the display layer */
    guac_protocol_send_move(socket, display->select_layer,
            display->display_layer, 0, 0, 0);

    /* Send select layer size */
    guac_protocol_send_size(socket, display->select_layer,
            display->char_width  * display->width,
            display->char_height * display->height);

}
コード例 #2
0
/**
 * Resizes and redraws the handle layer of the scrollbar according to the given
 * scrollbar render state, sending any necessary Guacamole instructions over
 * the given socket. The handle is the portion of the scrollbar that indicates
 * the current scroll value and which the user can click and drag to change the
 * value.
 *
 * @param scrollbar
 *     The scrollbar associated with the handle being resized and redrawn.
 *
 * @param state
 *     The guac_terminal_scrollbar_render_state describing the new scrollbar
 *     handle size and appearance.
 *
 * @param socket
 *     The guac_socket over which any instructions necessary to perform the
 *     render operation should be sent.
 */
static void guac_terminal_scrollbar_draw_handle(
        guac_terminal_scrollbar* scrollbar,
        guac_terminal_scrollbar_render_state* state,
        guac_socket* socket) {

    /* Set handle size */
    guac_protocol_send_size(socket, scrollbar->handle,
            state->handle_width,
            state->handle_height);

    /* Fill handle with solid color */
    guac_protocol_send_rect(socket, scrollbar->handle, 0, 0,
            state->handle_width,
            state->handle_height);

    guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->handle,
            0xA0, 0xA0, 0xA0, 0x8F);

}
コード例 #3
0
/**
 * Resizes and redraws the main scrollbar layer according to the given
 * scrollbar render state, sending any necessary Guacamole instructions over
 * the given socket.
 *
 * @param scrollbar
 *     The scrollbar to resize and redraw.
 *
 * @param state
 *     The guac_terminal_scrollbar_render_state describing the new scrollbar
 *     size and appearance.
 *
 * @param socket
 *     The guac_socket over which any instructions necessary to perform the
 *     render operation should be sent.
 */
static void guac_terminal_scrollbar_draw_container(
        guac_terminal_scrollbar* scrollbar,
        guac_terminal_scrollbar_render_state* state,
        guac_socket* socket) {

    /* Set container size */
    guac_protocol_send_size(socket, scrollbar->container,
            state->container_width,
            state->container_height);

    /* Fill container with solid color */
    guac_protocol_send_rect(socket, scrollbar->container, 0, 0,
            state->container_width,
            state->container_height);

    guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->container,
            0x80, 0x80, 0x80, 0x40);

}
コード例 #4
0
ファイル: scrollbar.c プロジェクト: 5ant/guacamole-server
void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar) {

    guac_socket* socket = scrollbar->client->socket;

    /* Get old state */
    int old_value = scrollbar->value;
    guac_terminal_scrollbar_render_state* old_state = &scrollbar->render_state;

    /* Calculate new state */
    int new_value;
    guac_terminal_scrollbar_render_state new_state;
    calculate_state(scrollbar, &new_state, &new_value);

    /* Notify of scroll if value is changing */
    if (new_value != old_value && scrollbar->scroll_handler)
        scrollbar->scroll_handler(scrollbar, new_value);

    /* Reposition container if moved */
    if (old_state->container_x != new_state.container_x
     || old_state->container_y != new_state.container_y) {

        guac_protocol_send_move(socket,
                scrollbar->container, scrollbar->parent,
                new_state.container_x,
                new_state.container_y,
                0);

    }

    /* Resize and redraw container if size changed */
    if (old_state->container_width  != new_state.container_width
     || old_state->container_height != new_state.container_height) {

        /* Set new size */
        guac_protocol_send_size(socket, scrollbar->container,
                new_state.container_width,
                new_state.container_height);

        /* Fill container with solid color */
        guac_protocol_send_rect(socket, scrollbar->container, 0, 0,
                new_state.container_width,
                new_state.container_height);

        guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->container,
                0x40, 0x40, 0x40, 0xFF);

    }

    /* Reposition handle if moved */
    if (old_state->handle_x != new_state.handle_x
     || old_state->handle_y != new_state.handle_y) {

        guac_protocol_send_move(socket,
                scrollbar->handle, scrollbar->container,
                new_state.handle_x,
                new_state.handle_y,
                0);

    }

    /* Resize and redraw handle if size changed */
    if (old_state->handle_width  != new_state.handle_width
     || old_state->handle_height != new_state.handle_height) {

        /* Send new size */
        guac_protocol_send_size(socket, scrollbar->handle,
                new_state.handle_width,
                new_state.handle_height);

        /* Fill and stroke handle with solid color */
        guac_protocol_send_rect(socket, scrollbar->handle, 0, 0,
                new_state.handle_width,
                new_state.handle_height);

        guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->handle,
                0x80, 0x80, 0x80, 0xFF);

        guac_protocol_send_cstroke(socket, GUAC_COMP_OVER, scrollbar->handle,
                GUAC_LINE_CAP_SQUARE, GUAC_LINE_JOIN_MITER, 2,
                0xA0, 0xA0, 0xA0, 0xFF);

    }

    /* Store current render state */
    scrollbar->render_state = new_state;

}
コード例 #5
0
ファイル: client.c プロジェクト: superactive/guacamole-server
int guac_client_init(guac_client* client, int argc, char** argv) {

    rfbClient* rfb_client;

    vnc_guac_client_data* guac_client_data;

    int retries_remaining;

    /* Set up libvncclient logging */
    rfbClientLog = guac_vnc_client_log_info;
    rfbClientErr = guac_vnc_client_log_error;

    /*** PARSE ARGUMENTS ***/

    if (argc != VNC_ARGS_COUNT) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Wrong argument count received.");
        return 1;
    }

    /* Alloc client data */
    guac_client_data = malloc(sizeof(vnc_guac_client_data));
    client->data = guac_client_data;

    guac_client_data->hostname = strdup(argv[IDX_HOSTNAME]);
    guac_client_data->port = atoi(argv[IDX_PORT]);

    /* Set remote cursor flag */
    guac_client_data->remote_cursor = (strcmp(argv[IDX_CURSOR], "remote") == 0);

    /* Set red/blue swap flag */
    guac_client_data->swap_red_blue = (strcmp(argv[IDX_SWAP_RED_BLUE], "true") == 0);

    /* Set read-only flag */
    guac_client_data->read_only = (strcmp(argv[IDX_READ_ONLY], "true") == 0);

    /* Freed after use by libvncclient */
    guac_client_data->password = strdup(argv[IDX_PASSWORD]);

    /* Parse color depth */
    guac_client_data->color_depth = atoi(argv[IDX_COLOR_DEPTH]);

#ifdef ENABLE_VNC_REPEATER
    /* Set repeater parameters if specified */
    if (argv[IDX_DEST_HOST][0] != '\0')
        guac_client_data->dest_host = strdup(argv[IDX_DEST_HOST]);
    else
        guac_client_data->dest_host = NULL;

    if (argv[IDX_DEST_PORT][0] != '\0')
        guac_client_data->dest_port = atoi(argv[IDX_DEST_PORT]);
#endif

    /* Set encodings if specified */
    if (argv[IDX_ENCODINGS][0] != '\0')
        guac_client_data->encodings = strdup(argv[IDX_ENCODINGS]);
    else
        guac_client_data->encodings = NULL;

    /* Parse autoretry */
    if (argv[IDX_AUTORETRY][0] != '\0')
        retries_remaining = atoi(argv[IDX_AUTORETRY]);
    else
        retries_remaining = 0; 

#ifdef ENABLE_VNC_LISTEN
    /* Set reverse-connection flag */
    guac_client_data->reverse_connect =
        (strcmp(argv[IDX_REVERSE_CONNECT], "true") == 0);

    /* Parse listen timeout */
    if (argv[IDX_LISTEN_TIMEOUT][0] != '\0')
        guac_client_data->listen_timeout = atoi(argv[IDX_LISTEN_TIMEOUT]);
    else
        guac_client_data->listen_timeout = 5000;
#endif

    /* Init clipboard */
    guac_client_data->clipboard = guac_common_clipboard_alloc(GUAC_VNC_CLIPBOARD_MAX_LENGTH);

    /* Ensure connection is kept alive during lengthy connects */
    guac_socket_require_keep_alive(client->socket);

    /* Attempt connection */
    rfb_client = __guac_vnc_get_client(client);

    /* If unsuccessful, retry as many times as specified */
    while (!rfb_client && retries_remaining > 0) {

        guac_client_log_info(client,
                "Connect failed. Waiting %ims before retrying...",
                GUAC_VNC_CONNECT_INTERVAL);

        /* Wait for given interval then retry */
        usleep(GUAC_VNC_CONNECT_INTERVAL*1000);
        rfb_client = __guac_vnc_get_client(client);
        retries_remaining--;

    }

    /* If the final connect attempt fails, return error */
    if (!rfb_client) {
        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to connect to VNC server.");
        return 1;
    }

#ifdef ENABLE_PULSE
    guac_client_data->audio_enabled =
        (strcmp(argv[IDX_ENABLE_AUDIO], "true") == 0);

    /* If an encoding is available, load an audio stream */
    if (guac_client_data->audio_enabled) {    

        guac_client_data->audio = guac_audio_stream_alloc(client, NULL);

        /* Load servername if specified */
        if (argv[IDX_AUDIO_SERVERNAME][0] != '\0')
            guac_client_data->pa_servername =
                strdup(argv[IDX_AUDIO_SERVERNAME]);
        else
            guac_client_data->pa_servername = NULL;

        /* If successful, init audio system */
        if (guac_client_data->audio != NULL) {
            
            guac_client_log_info(client,
                    "Audio will be encoded as %s",
                    guac_client_data->audio->encoder->mimetype);

            /* Require threadsafe sockets if audio enabled */
            guac_socket_require_threadsafe(client->socket);

            /* Start audio stream */
            guac_pa_start_stream(client);
            
        }

        /* Otherwise, audio loading failed */
        else
            guac_client_log_info(client,
                    "No available audio encoding. Sound disabled.");

    } /* end if audio enabled */
#endif

    /* Set remaining client data */
    guac_client_data->rfb_client = rfb_client;
    guac_client_data->copy_rect_used = 0;
    guac_client_data->cursor = guac_client_alloc_buffer(client);

    /* Set handlers */
    client->handle_messages = vnc_guac_client_handle_messages;
    client->free_handler = vnc_guac_client_free_handler;

    /* If not read-only, set input handlers and pointer */
    if (guac_client_data->read_only == 0) {

        /* Only handle mouse/keyboard/clipboard if not read-only */
        client->mouse_handler = vnc_guac_client_mouse_handler;
        client->key_handler = vnc_guac_client_key_handler;
        client->clipboard_handler = vnc_guac_client_clipboard_handler;
        client->blob_handler = vnc_guac_client_blob_handler;
        client->end_handler = vnc_guac_client_end_handler;

        /* If not read-only but cursor is remote, set a dot cursor */
        if (guac_client_data->remote_cursor)
            guac_common_set_dot_cursor(client);

        /* Otherwise, set pointer until explicitly requested otherwise */
        else
            guac_common_set_pointer_cursor(client);

    }

    /* Send name */
    guac_protocol_send_name(client->socket, rfb_client->desktopName);

    /* Send size */
    guac_protocol_send_size(client->socket,
            GUAC_DEFAULT_LAYER, rfb_client->width, rfb_client->height);

    return 0;

}
コード例 #6
0
ファイル: client.c プロジェクト: uplusplus/guacamole-server
int guac_client_init(guac_client* client, int argc, char** argv) {

    rdp_guac_client_data* guac_client_data;

    freerdp* rdp_inst;
    rdpSettings* settings;

    char* hostname;
    int port = RDP_DEFAULT_PORT;
    boolean bitmap_cache;

    /**
     * Selected server-side keymap. Client will be assumed to also use this
     * keymap. Keys will be sent to server based on client input on a
     * best-effort basis.
     */
    const guac_rdp_keymap* chosen_keymap;

    if (argc < RDP_ARGS_COUNT) {

        guac_protocol_send_error(client->socket,
                                 "Wrong argument count received.");
        guac_socket_flush(client->socket);

        guac_error = GUAC_STATUS_BAD_ARGUMENT;
        guac_error_message = "Wrong argument count received";

        return 1;
    }

    /* If port specified, use it */
    if (argv[IDX_PORT][0] != '\0')
        port = atoi(argv[IDX_PORT]);

    hostname = argv[IDX_HOSTNAME];

    /* Allocate client data */
    guac_client_data = malloc(sizeof(rdp_guac_client_data));

    /* Init random number generator */
    srandom(time(NULL));

    /* Init client */
    freerdp_channels_global_init();
    rdp_inst = freerdp_new();
    rdp_inst->PreConnect = rdp_freerdp_pre_connect;
    rdp_inst->PostConnect = rdp_freerdp_post_connect;
    rdp_inst->ReceiveChannelData = __guac_receive_channel_data;

    /* Allocate FreeRDP context */
    rdp_inst->context_size = sizeof(rdp_freerdp_context);
    rdp_inst->ContextNew  = (pContextNew) rdp_freerdp_context_new;
    rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free;
    freerdp_context_new(rdp_inst);

    /* Set settings */
    settings = rdp_inst->settings;

    /* Console */
    settings->console_session = (strcmp(argv[IDX_CONSOLE], "true") == 0);
    settings->console_audio   = (strcmp(argv[IDX_CONSOLE_AUDIO], "true") == 0);

    /* --no-auth */
    settings->authentication = false;

    /* --sec rdp */
    settings->rdp_security = true;
    settings->tls_security = false;
    settings->nla_security = false;
    settings->encryption = true;
    settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
    settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;

    /* Use optimal width unless overridden */
    settings->width = client->info.optimal_width;
    if (argv[IDX_WIDTH][0] != '\0')
        settings->width = atoi(argv[IDX_WIDTH]);

    /* Use default width if given width is invalid. */
    if (settings->width <= 0) {
        settings->width = RDP_DEFAULT_WIDTH;
        guac_client_log_error(client,
                              "Invalid width: \"%s\". Using default of %i.",
                              argv[IDX_WIDTH], settings->width);
    }

    /* Round width up to nearest multiple of 4 */
    settings->width = (settings->width + 3) & ~0x3;

    /* Use optimal height unless overridden */
    settings->height = client->info.optimal_height;
    if (argv[IDX_HEIGHT][0] != '\0')
        settings->height = atoi(argv[IDX_HEIGHT]);

    /* Use default height if given height is invalid. */
    if (settings->height <= 0) {
        settings->height = RDP_DEFAULT_HEIGHT;
        guac_client_log_error(client,
                              "Invalid height: \"%s\". Using default of %i.",
                              argv[IDX_WIDTH], settings->height);
    }

    /* Set hostname */
    settings->hostname = strdup(hostname);
    settings->port = port;
    settings->window_title = strdup(hostname);

    /* Domain */
    if (argv[IDX_DOMAIN][0] != '\0')
        settings->domain = strdup(argv[IDX_DOMAIN]);

    /* Username */
    if (argv[IDX_USERNAME][0] != '\0')
        settings->username = strdup(argv[IDX_USERNAME]);

    /* Password */
    if (argv[IDX_PASSWORD][0] != '\0') {
        settings->password = strdup(argv[IDX_PASSWORD]);
        settings->autologon = 1;
    }

    /* Initial program */
    if (argv[IDX_INITIAL_PROGRAM][0] != '\0')
        settings->shell = strdup(argv[IDX_INITIAL_PROGRAM]);

    /* Session color depth */
    settings->color_depth = RDP_DEFAULT_DEPTH;
    if (argv[IDX_COLOR_DEPTH][0] != '\0')
        settings->color_depth = atoi(argv[IDX_COLOR_DEPTH]);

    /* Use default depth if given depth is invalid. */
    if (settings->color_depth == 0) {
        settings->color_depth = RDP_DEFAULT_DEPTH;
        guac_client_log_error(client,
                              "Invalid color-depth: \"%s\". Using default of %i.",
                              argv[IDX_WIDTH], settings->color_depth);
    }

    /* Audio enable/disable */
    guac_client_data->audio_enabled =
        (strcmp(argv[IDX_DISABLE_AUDIO], "true") != 0);

    /* Printing enable/disable */
    guac_client_data->printing_enabled =
        (strcmp(argv[IDX_ENABLE_PRINTING], "true") == 0);

    /* Order support */
    bitmap_cache = settings->bitmap_cache;
    settings->os_major_type = OSMAJORTYPE_UNSPECIFIED;
    settings->os_minor_type = OSMINORTYPE_UNSPECIFIED;
    settings->order_support[NEG_DSTBLT_INDEX] = true;
    settings->order_support[NEG_PATBLT_INDEX] = false; /* PATBLT not yet supported */
    settings->order_support[NEG_SCRBLT_INDEX] = true;
    settings->order_support[NEG_OPAQUE_RECT_INDEX] = true;
    settings->order_support[NEG_DRAWNINEGRID_INDEX] = false;
    settings->order_support[NEG_MULTIDSTBLT_INDEX] = false;
    settings->order_support[NEG_MULTIPATBLT_INDEX] = false;
    settings->order_support[NEG_MULTISCRBLT_INDEX] = false;
    settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = false;
    settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false;
    settings->order_support[NEG_LINETO_INDEX] = false;
    settings->order_support[NEG_POLYLINE_INDEX] = false;
    settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache;
    settings->order_support[NEG_MEM3BLT_INDEX] = false;
    settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
    settings->order_support[NEG_MEM3BLT_V2_INDEX] = false;
    settings->order_support[NEG_SAVEBITMAP_INDEX] = false;
    settings->order_support[NEG_GLYPH_INDEX_INDEX] = true;
    settings->order_support[NEG_FAST_INDEX_INDEX] = true;
    settings->order_support[NEG_FAST_GLYPH_INDEX] = true;
    settings->order_support[NEG_POLYGON_SC_INDEX] = false;
    settings->order_support[NEG_POLYGON_CB_INDEX] = false;
    settings->order_support[NEG_ELLIPSE_SC_INDEX] = false;
    settings->order_support[NEG_ELLIPSE_CB_INDEX] = false;

    /* Store client data */
    guac_client_data->rdp_inst = rdp_inst;
    guac_client_data->bounded = false;
    guac_client_data->mouse_button_mask = 0;
    guac_client_data->current_surface = GUAC_DEFAULT_LAYER;
    guac_client_data->clipboard = NULL;
    guac_client_data->audio = NULL;

    /* Main socket needs to be threadsafe */
    guac_socket_require_threadsafe(client->socket);

    /* Recursive attribute for locks */
    pthread_mutexattr_init(&(guac_client_data->attributes));
    pthread_mutexattr_settype(&(guac_client_data->attributes),
                              PTHREAD_MUTEX_RECURSIVE);

    /* Init RDP lock */
    pthread_mutex_init(&(guac_client_data->rdp_lock),
                       &(guac_client_data->attributes));

    /* Clear keysym state mapping and keymap */
    memset(guac_client_data->keysym_state, 0,
           sizeof(guac_rdp_keysym_state_map));

    memset(guac_client_data->keymap, 0,
           sizeof(guac_rdp_static_keymap));

    client->data = guac_client_data;
    ((rdp_freerdp_context*) rdp_inst->context)->client = client;

    /* Pick keymap based on argument */
    if (argv[IDX_SERVER_LAYOUT][0] != '\0') {

        /* US English Qwerty */
        if (strcmp("en-us-qwerty", argv[IDX_SERVER_LAYOUT]) == 0)
            chosen_keymap = &guac_rdp_keymap_en_us;

        /* German Qwertz */
        else if (strcmp("de-de-qwertz", argv[IDX_SERVER_LAYOUT]) == 0)
            chosen_keymap = &guac_rdp_keymap_de_de;

        /* French Azerty */
        else if (strcmp("fr-fr-azerty", argv[IDX_SERVER_LAYOUT]) == 0)
            chosen_keymap = &guac_rdp_keymap_fr_fr;

        /* Failsafe (Unicode) keymap */
        else if (strcmp("failsafe", argv[IDX_SERVER_LAYOUT]) == 0)
            chosen_keymap = &guac_rdp_keymap_failsafe;

        /* If keymap unknown, resort to failsafe */
        else {

            guac_client_log_error(client,
                                  "Unknown layout \"%s\". Using the failsafe layout instead.",
                                  argv[IDX_SERVER_LAYOUT]);

            chosen_keymap = &guac_rdp_keymap_failsafe;

        }

    }

    /* If no keymap requested, assume US */
    else
        chosen_keymap = &guac_rdp_keymap_en_us;

    /* Load keymap into client */
    __guac_rdp_client_load_keymap(client, chosen_keymap);

    /* Set server-side keymap */
    settings->kbd_layout = chosen_keymap->freerdp_keyboard_layout;

    /* Connect to RDP server */
    if (!freerdp_connect(rdp_inst)) {

        guac_protocol_send_error(client->socket,
                                 "Error connecting to RDP server");
        guac_socket_flush(client->socket);

        guac_error = GUAC_STATUS_BAD_STATE;
        guac_error_message = "Error connecting to RDP server";

        return 1;
    }

    /* Send connection name */
    guac_protocol_send_name(client->socket, settings->window_title);

    /* Send size */
    guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
                            settings->width, settings->height);

    /* Create glyph surfaces */
    guac_client_data->opaque_glyph_surface = cairo_image_surface_create(
                CAIRO_FORMAT_RGB24, settings->width, settings->height);

    guac_client_data->trans_glyph_surface = cairo_image_surface_create(
            CAIRO_FORMAT_ARGB32, settings->width, settings->height);

    /* Set default pointer */
    guac_rdp_set_default_pointer(client);

    /* Success */
    return 0;

}
コード例 #7
0
/**
 * Guacamole client plugin entry point. This function will be called by guacd
 * when the protocol associated with this plugin is selected.
 *
 * @param client
 *     A newly-allocated guac_client structure representing the client which
 *     connected to guacd.
 *
 * @param argc
 *     The number of arguments within the argv array.
 *
 * @param argv
 *     All arguments passed during the Guacamole protocol handshake. These
 *     arguments correspond identically in both order and number to the
 *     arguments listed in GUAC_CLIENT_ARGS.
 */
int guac_client_init(guac_client* client, int argc, char** argv) {

    /* Validate argument count */
    if (argc != STREAMTEST_ARGS_COUNT) {
        guac_client_log(client, GUAC_LOG_ERROR, "Wrong number of arguments.");
        return 1;
    }

    /* Allocate stream for media */
    streamtest_playback_mode mode;
    guac_stream* stream = guac_client_alloc_stream(client);

    /* Determine playback mode from mimetype */
    if (strncmp(argv[IDX_MIMETYPE], "audio/", 6) == 0) {
        mode = STREAMTEST_AUDIO;
        guac_client_log(client, GUAC_LOG_DEBUG,
                "Recognized type \"%s\" as audio",
                argv[IDX_MIMETYPE]);
    }
    else if (strncmp(argv[IDX_MIMETYPE], "video/", 6) == 0) {
        mode = STREAMTEST_VIDEO;
        guac_client_log(client, GUAC_LOG_DEBUG,
                "Recognized type \"%s\" as video",
                argv[IDX_MIMETYPE]);
    }

    /* Abort if type cannot be recognized */
    else {
        guac_client_log(client, GUAC_LOG_ERROR,
                "Invalid media type \"%s\" (not audio nor video)",
                argv[IDX_MIMETYPE]);
        return 1;
    }

    /* Initialize streaming depending on playback mode */
    switch (mode) {

        /* Set up progress bar for audio streams */
        case STREAMTEST_AUDIO:

            /* Begin audio stream */
            guac_protocol_send_audio(client->socket, stream,
                    argv[IDX_MIMETYPE]);

            /* Init display */
            guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
                    STREAMTEST_PROGRESS_WIDTH,
                    STREAMTEST_PROGRESS_HEIGHT);
            break;

        /* Set up generic video area for video streams */
        case STREAMTEST_VIDEO:

            /* Begin video stream */
            guac_protocol_send_video(client->socket, stream,
                    GUAC_DEFAULT_LAYER, argv[IDX_MIMETYPE]);

            /* Init display */
            guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER,
                    client->info.optimal_width,
                    client->info.optimal_height);
            break;

        /* There are no other playback modes */
        default:
            assert(false);

    }

    /* Attempt to open specified file, abort on error */
    int fd = open(argv[IDX_FILENAME], O_RDONLY);
    if (fd == -1) {
        guac_client_log(client, GUAC_LOG_ERROR,
                "Unable to open \"%s\": %s",
                argv[IDX_FILENAME], strerror(errno));
        return 1;
    }

    int file_size = streamtest_get_file_size(fd);
    if (file_size == -1) {
        guac_client_log(client, GUAC_LOG_ERROR,
                "Unable to determine size of file \"%s\": %s",
                argv[IDX_FILENAME], strerror(errno));
        return 1;
    }

    guac_client_log(client, GUAC_LOG_DEBUG,
            "Successfully opened file \"%s\" (%i bytes)",
            argv[IDX_FILENAME], file_size);

    /* Allocate state structure */
    streamtest_state* state = malloc(sizeof(streamtest_state));

    /* Set frame duration/size */
    state->frame_duration = atoi(argv[IDX_FRAME_USECS]);
    state->frame_bytes    = atoi(argv[IDX_BYTES_PER_FRAME]);
    state->frame_buffer   = malloc(state->frame_bytes);

    guac_client_log(client, GUAC_LOG_DEBUG,
            "Frames will last %i microseconds and contain %i bytes",
            state->frame_duration, state->frame_bytes);

    /* Start with the file closed, playback not paused */
    state->mode = mode;
    state->stream = stream;
    state->fd = fd;
    state->paused = false;
    state->file_size = file_size;

    /* Set client handlers and data */
    client->handle_messages = streamtest_client_message_handler;
    client->key_handler     = streamtest_client_key_handler;
    client->free_handler    = streamtest_client_free_handler;
    client->data = state;

    /* Render initial progress bar */
    streamtest_render_progress(client);
    guac_socket_flush(client->socket);

    /* Initialization complete */
    return 0;

}
コード例 #8
0
ファイル: display.c プロジェクト: tamx/guacamole-server
void guac_terminal_display_resize(guac_terminal_display* display, int width, int height) {

    guac_terminal_operation* current;
    int x, y;

    /* Fill with background color */
    guac_terminal_char fill = {
        .value = 0,
        .attributes = {
            .foreground = display->default_background,
            .background = display->default_background
        },
        .width = 1
    };

    /* Free old operations buffer */
    if (display->operations != NULL)
        free(display->operations);

    /* Alloc operations */
    display->operations = malloc(width * height *
            sizeof(guac_terminal_operation));

    /* Init each operation buffer row */
    current = display->operations;
    for (y=0; y<height; y++) {

        /* Init entire row to NOP */
        for (x=0; x<width; x++) {

            /* If on old part of screen, do not clear */
            if (x < display->width && y < display->height)
                current->type = GUAC_CHAR_NOP;

            /* Otherwise, clear contents first */
            else {
                current->type = GUAC_CHAR_SET;
                current->character  = fill;
            }

            current++;

        }

    }

    /* Set width and height */
    display->width = width;
    display->height = height;

    /* Send display size */
    guac_common_surface_resize(
            display->display_surface,
            display->char_width  * width,
            display->char_height * height);

    guac_protocol_send_size(display->client->socket,
            display->select_layer,
            display->char_width  * width,
            display->char_height * height);

    /* If selection visible and committed, clear */
    if (display->text_selected && display->selection_committed)
        __guac_terminal_display_clear_select(display);

}
コード例 #9
0
ファイル: client.c プロジェクト: BillTheBest/html5rdp
int guac_client_init(guac_client* client, int argc, char** argv) {

    rfbClient* rfb_client;

    vnc_guac_client_data* guac_client_data;

    int read_only;

    /* Set up libvncclient logging */
    rfbClientLog = guac_vnc_client_log_info;
    rfbClientErr = guac_vnc_client_log_error;

    /*** PARSE ARGUMENTS ***/

    if (argc != VNC_ARGS_COUNT) {
        guac_protocol_send_error(client->socket, "Wrong argument count received.");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Alloc client data */
    guac_client_data = malloc(sizeof(vnc_guac_client_data));
    client->data = guac_client_data;

    /* Set read-only flag */
    read_only = (strcmp(argv[IDX_READ_ONLY], "true") == 0);

    /* Set red/blue swap flag */
    guac_client_data->swap_red_blue = (strcmp(argv[IDX_SWAP_RED_BLUE], "true") == 0);

    /* Freed after use by libvncclient */
    guac_client_data->password = strdup(argv[IDX_PASSWORD]);

    /*** INIT RFB CLIENT ***/

    rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */

    /* Store Guac client in rfb client */
    rfbClientSetClientData(rfb_client, __GUAC_CLIENT, client);

    /* Framebuffer update handler */
    rfb_client->GotFrameBufferUpdate = guac_vnc_update;
    rfb_client->GotCopyRect = guac_vnc_copyrect;

    /* Do not handle clipboard and local cursor if read-only */
    if (read_only == 0) {
        /* Enable client-side cursor */
        rfb_client->GotCursorShape = guac_vnc_cursor;
        rfb_client->appData.useRemoteCursor = TRUE;

        /* Clipboard */
        rfb_client->GotXCutText = guac_vnc_cut_text;
    }

    /* Password */
    rfb_client->GetPassword = guac_vnc_get_password;

    /* Depth */
    guac_vnc_set_pixel_format(rfb_client, atoi(argv[IDX_COLOR_DEPTH]));

#ifdef ENABLE_PULSE
    guac_client_data->audio_enabled =
        (strcmp(argv[IDX_ENABLE_AUDIO], "true") == 0);

    /* If an encoding is available, load an audio stream */
    if (guac_client_data->audio_enabled) {    

        guac_client_data->audio = guac_audio_stream_alloc(client, NULL);

        /* Load servername if specified */
        if (argv[IDX_AUDIO_SERVERNAME][0] != '\0')
            guac_client_data->pa_servername =
                strdup(argv[IDX_AUDIO_SERVERNAME]);
        else
            guac_client_data->pa_servername = NULL;

        /* If successful, init audio system */
        if (guac_client_data->audio != NULL) {
            
            guac_client_log_info(client,
                    "Audio will be encoded as %s",
                    guac_client_data->audio->encoder->mimetype);

            /* Require threadsafe sockets if audio enabled */
            guac_socket_require_threadsafe(client->socket);

            /* Start audio stream */
            guac_pa_start_stream(client);
            
        }

        /* Otherwise, audio loading failed */
        else
            guac_client_log_info(client,
                    "No available audio encoding. Sound disabled.");

    } /* end if audio enabled */
#endif

    /* Hook into allocation so we can handle resize. */
    guac_client_data->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer;
    rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer;
    rfb_client->canHandleNewFBSize = 1;

    /* Set hostname and port */
    rfb_client->serverHost = strdup(argv[0]);
    rfb_client->serverPort = atoi(argv[1]);

#ifdef ENABLE_VNC_REPEATER
    /* Set repeater parameters if specified */
    if(argv[IDX_DEST_HOST][0] != '\0')
        rfb_client->destHost = strdup(argv[IDX_DEST_HOST]);

    if(argv[IDX_DEST_PORT][0] != '\0')
        rfb_client->destPort = atoi(argv[IDX_DEST_PORT]);
#endif

    /* Set encodings if specified */
    if (argv[IDX_ENCODINGS][0] != '\0')
        rfb_client->appData.encodingsString = guac_client_data->encodings
            = strdup(argv[IDX_ENCODINGS]);
    else
        guac_client_data->encodings = NULL;

    /* Connect */

    if (!rfbInitClient(rfb_client, NULL, NULL)) {
        guac_protocol_send_error(client->socket, "Error initializing VNC client");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Set remaining client data */
    guac_client_data->rfb_client = rfb_client;
    guac_client_data->copy_rect_used = 0;
    guac_client_data->cursor = guac_client_alloc_buffer(client);

    /* Set handlers */
    client->handle_messages = vnc_guac_client_handle_messages;
    client->free_handler = vnc_guac_client_free_handler;
    if (read_only == 0) {
        /* Do not handle mouse/keyboard/clipboard if read-only */
        client->mouse_handler = vnc_guac_client_mouse_handler;
        client->key_handler = vnc_guac_client_key_handler;
        client->clipboard_handler = vnc_guac_client_clipboard_handler;
    }

    /* Send name */
    guac_protocol_send_name(client->socket, rfb_client->desktopName);

    /* Send size */
    guac_protocol_send_size(client->socket,
            GUAC_DEFAULT_LAYER, rfb_client->width, rfb_client->height);

    return 0;

}
コード例 #10
0
ファイル: client.c プロジェクト: bartlamboo/guacamole-server
int guac_client_init(guac_client* client, int argc, char** argv) {

    rfbClient* rfb_client;

    vnc_guac_client_data* guac_client_data;

    int read_only;

    /* Set up libvncclient logging */
    rfbClientLog = guac_vnc_client_log_info;
    rfbClientErr = guac_vnc_client_log_error;

    /*** PARSE ARGUMENTS ***/

    if (argc < 7) {
        guac_protocol_send_error(client->socket, "Wrong argument count received.");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Alloc client data */
    guac_client_data = malloc(sizeof(vnc_guac_client_data));
    client->data = guac_client_data;

    /* Set read-only flag */
    read_only = (strcmp(argv[2], "true") == 0);

    /* Set red/blue swap flag */
    guac_client_data->swap_red_blue = (strcmp(argv[5], "true") == 0);

    /* Freed after use by libvncclient */
    guac_client_data->password = strdup(argv[4]);

    /*** INIT RFB CLIENT ***/

    rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */

    /* Store Guac client in rfb client */
    rfbClientSetClientData(rfb_client, __GUAC_CLIENT, client);

    /* Framebuffer update handler */
    rfb_client->GotFrameBufferUpdate = guac_vnc_update;
    rfb_client->GotCopyRect = guac_vnc_copyrect;

    /* Do not handle clipboard and local cursor if read-only */
    if (read_only == 0) {
        /* Enable client-side cursor */
        rfb_client->GotCursorShape = guac_vnc_cursor;
        rfb_client->appData.useRemoteCursor = TRUE;

        /* Clipboard */
        rfb_client->GotXCutText = guac_vnc_cut_text;
    }

    /* Password */
    rfb_client->GetPassword = guac_vnc_get_password;

    /* Depth */
    guac_vnc_set_pixel_format(rfb_client, atoi(argv[6]));

    /* Hook into allocation so we can handle resize. */
    guac_client_data->rfb_MallocFrameBuffer = rfb_client->MallocFrameBuffer;
    rfb_client->MallocFrameBuffer = guac_vnc_malloc_framebuffer;
    rfb_client->canHandleNewFBSize = 1;

    /* Set hostname and port */
    rfb_client->serverHost = strdup(argv[0]);
    rfb_client->serverPort = atoi(argv[1]);

    /* Set encodings if specified */
    if (argv[3][0] != '\0')
        rfb_client->appData.encodingsString = guac_client_data->encodings = strdup(argv[3]);
    else
        guac_client_data->encodings = NULL;

    /* Connect */
    if (!rfbInitClient(rfb_client, NULL, NULL)) {
        guac_protocol_send_error(client->socket, "Error initializing VNC client");
        guac_socket_flush(client->socket);
        return 1;
    }

    /* Set remaining client data */
    guac_client_data->rfb_client = rfb_client;
    guac_client_data->copy_rect_used = 0;
    guac_client_data->cursor = guac_client_alloc_buffer(client);

    /* Set handlers */
    client->handle_messages = vnc_guac_client_handle_messages;
    client->free_handler = vnc_guac_client_free_handler;
    if (read_only == 0) {
        /* Do not handle mouse/keyboard/clipboard if read-only */
        client->mouse_handler = vnc_guac_client_mouse_handler;
        client->key_handler = vnc_guac_client_key_handler;
        client->clipboard_handler = vnc_guac_client_clipboard_handler;
    }

    /* Send name */
    guac_protocol_send_name(client->socket, rfb_client->desktopName);

    /* Send size */
    guac_protocol_send_size(client->socket,
                            GUAC_DEFAULT_LAYER, rfb_client->width, rfb_client->height);

    return 0;

}