void guac_common_set_pointer_cursor(guac_user* user) {

    guac_client* client = user->client;
    guac_socket* socket = user->socket;

    /* Draw to buffer */
    guac_layer* cursor = guac_client_alloc_buffer(client);

    cairo_surface_t* graphic = cairo_image_surface_create_for_data(
            guac_common_pointer_cursor,
            guac_common_pointer_cursor_format,
            guac_common_pointer_cursor_width,
            guac_common_pointer_cursor_height,
            guac_common_pointer_cursor_stride);

    guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor,
            0, 0, graphic);
    cairo_surface_destroy(graphic);

    /* Set cursor */
    guac_protocol_send_cursor(socket, 0, 0, cursor,
            0, 0,
            guac_common_pointer_cursor_width,
            guac_common_pointer_cursor_height);

    /* Free buffer */
    guac_client_free_buffer(client, cursor);

    guac_client_log(client, GUAC_LOG_DEBUG,
            "Client cursor image set to generic built-in pointer.");

}
Exemplo n.º 2
0
void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) {

    guac_client* client = ((rdp_freerdp_context*) context)->client;
    guac_socket* socket = client->socket; 

    /* Allocate surface */
    guac_layer* buffer = guac_client_alloc_buffer(client);
    guac_common_surface* surface = guac_common_surface_alloc(socket, buffer, bitmap->width, bitmap->height);

    /* Cache image data if present */
    if (bitmap->data != NULL) {

        /* Create surface from image data */
        cairo_surface_t* image = cairo_image_surface_create_for_data(
            bitmap->data, CAIRO_FORMAT_RGB24,
            bitmap->width, bitmap->height, 4*bitmap->width);

        /* Send surface to buffer */
        guac_common_surface_draw(surface, 0, 0, image);

        /* Free surface */
        cairo_surface_destroy(image);

    }

    /* Store buffer reference in bitmap */
    ((guac_rdp_bitmap*) bitmap)->buffer = buffer;
    ((guac_rdp_bitmap*) bitmap)->surface = surface;

}
Exemplo n.º 3
0
void test_buffer_pool() {

    guac_client* client;

    int i;
    int seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0};

    guac_layer* layer;

    /* Get client */
    client = guac_client_alloc();
    CU_ASSERT_PTR_NOT_NULL_FATAL(client);

    /* Fill pool */
    for (i=0; i<GUAC_BUFFER_POOL_INITIAL_SIZE; i++) {

        /* Allocate and throw away a layer (should not disturb buffer alloc) */
        CU_ASSERT_PTR_NOT_NULL_FATAL(guac_client_alloc_layer(client));

        layer = guac_client_alloc_buffer(client);

        /* Index should be within pool size */
        CU_ASSERT_PTR_NOT_NULL_FATAL(layer);
        CU_ASSERT_FATAL(layer->index < 0);
        CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE);

        /* This should be a layer we have not seen yet */
        CU_ASSERT_FALSE(seen[-layer->index - 1]);
        seen[-layer->index - 1] = 1;

        guac_client_free_buffer(client, layer);

    }

    /* Now that pool is filled, we should get a previously seen layer */
    layer = guac_client_alloc_buffer(client);

    CU_ASSERT_FATAL(layer->index < 0);
    CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE);
    CU_ASSERT_TRUE(seen[-layer->index - 1]);

    /* Free client */
    guac_client_free(client);

}
guac_common_display_layer* guac_common_display_alloc_buffer(
        guac_common_display* display, int width, int height) {

    guac_layer* buffer;
    guac_common_surface* surface;

    /* Allocate Guacamole buffer */
    buffer = guac_client_alloc_buffer(display->client);

    /* Allocate corresponding surface */
    surface = guac_common_surface_alloc(display->client,
            display->client->socket, buffer, width, height);

    /* Add buffer and surface to list */
    return guac_common_display_add_layer(&display->buffers, buffer, surface);

}
Exemplo n.º 5
0
void guac_rdp_pointer_new(rdpContext* context, rdpPointer* pointer) {

    guac_client* client = ((rdp_freerdp_context*) context)->client;
    guac_socket* socket = client->socket;

    /* Allocate data for image */
    unsigned char* data =
        (unsigned char*) malloc(pointer->width * pointer->height * 4);

    /* Allocate layer */
    guac_layer* buffer = guac_client_alloc_buffer(client);

    cairo_surface_t* surface;

    /* Convert to alpha cursor if mask data present */
    if (pointer->andMaskData && pointer->xorMaskData)
        freerdp_alpha_cursor_convert(data,
                pointer->xorMaskData, pointer->andMaskData,
                pointer->width, pointer->height, pointer->xorBpp,
                ((rdp_freerdp_context*) context)->clrconv);

    /* Create surface from image data */
    surface = cairo_image_surface_create_for_data(
        data, CAIRO_FORMAT_ARGB32,
        pointer->width, pointer->height, 4*pointer->width);

    /* Send surface to buffer */
    guac_protocol_send_png(socket, GUAC_COMP_SRC, buffer, 0, 0, surface);

    /* Free surface */
    cairo_surface_destroy(surface);
    free(data);

    /* Remember buffer */
    ((guac_rdp_pointer*) pointer)->layer = buffer;

}
Exemplo n.º 6
0
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;

}
Exemplo n.º 7
0
void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) {

    /*
     * Note that this is not a full implementation of PATBLT. This is a
     * fallback implementation which only renders a solid block of background
     * color using the specified ROP3 operation, ignoring whatever brush
     * was actually specified.
     *
     * As libguac-client-rdp explicitly tells the server not to send PATBLT,
     * well-behaved RDP servers will not use this operation at all, while
     * others will at least have a fallback.
     */

    /* Get client and current layer */
    guac_client* client = ((rdp_freerdp_context*) context)->client;
    const guac_layer* current_layer =
        ((rdp_guac_client_data*) client->data)->current_surface;

    int x = patblt->nLeftRect;
    int y = patblt->nTopRect;
    int w = patblt->nWidth;
    int h = patblt->nHeight;

    rdp_guac_client_data* data = (rdp_guac_client_data*) client->data;

    /* Layer for actual transfer */
    guac_layer* buffer;

    /*
     * Warn that rendering is a fallback, as the server should not be sending
     * this order.
     */
    guac_client_log_info(client, "Using fallback PATBLT (server is ignoring "
            "negotiated client capabilities)");

    /* Clip operation to bounds */
    __guac_rdp_clip_rect(data, &x, &y, &w, &h);

    /* Render rectangle based on ROP */
    switch (patblt->bRop) {

        /* If blackness, send black rectangle */
        case 0x00:
            guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);

            guac_protocol_send_cfill(client->socket,
                    GUAC_COMP_OVER, current_layer,
                    0x00, 0x00, 0x00, 0xFF);
            break;

        /* If NOP, do nothing */
        case 0xAA:
            break;

        /* If operation is just a copy, send foreground only */
        case 0xCC:
        case 0xF0:
            guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);

            guac_protocol_send_cfill(client->socket,
                    GUAC_COMP_OVER, current_layer,
                    (patblt->foreColor >> 16) & 0xFF,
                    (patblt->foreColor >> 8 ) & 0xFF,
                    (patblt->foreColor      ) & 0xFF,
                    0xFF);
            break;

        /* If whiteness, send white rectangle */
        case 0xFF:
            guac_protocol_send_rect(client->socket, current_layer, x, y, w, h);

            guac_protocol_send_cfill(client->socket,
                    GUAC_COMP_OVER, current_layer,
                    0xFF, 0xFF, 0xFF, 0xFF);
            break;

        /* Otherwise, invert entire rect */
        default:

            /* Allocate buffer for transfer */
            buffer = guac_client_alloc_buffer(client);

            /* Send rectangle stroke */
            guac_protocol_send_rect(client->socket, buffer,
                    0, 0, w, h);

            /* Fill rectangle with fore color only */
            guac_protocol_send_cfill(client->socket, GUAC_COMP_OVER, buffer,
                    0xFF, 0xFF, 0xFF, 0xFF);

            /* Transfer */
            guac_protocol_send_transfer(client->socket,

                    /* ... from buffer */
                    buffer, 0, 0, w, h,

                    /* ... inverting */
                    GUAC_TRANSFER_BINARY_XOR,

                    /* ... to current layer */
                    current_layer, x, y);

            /* Done with buffer */
            guac_client_free_buffer(client, buffer);

    }

}
Exemplo n.º 8
0
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]);
    guac_client_data->password = strdup(argv[IDX_PASSWORD]); /* NOTE: freed by libvncclient */
    guac_client_data->default_surface = NULL;

    /* Set flags */
    guac_client_data->remote_cursor = (strcmp(argv[IDX_CURSOR], "remote") == 0);
    guac_client_data->swap_red_blue = (strcmp(argv[IDX_SWAP_RED_BLUE], "true") == 0);
    guac_client_data->read_only     = (strcmp(argv[IDX_READ_ONLY], "true") == 0);

    /* 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);

    /* Configure clipboard encoding */
    if (guac_vnc_set_clipboard_encoding(client, argv[IDX_CLIPBOARD_ENCODING]))
        guac_client_log(client, GUAC_LOG_INFO,
                "Using non-standard VNC clipboard encoding: '%s'.",
                argv[IDX_CLIPBOARD_ENCODING]);

    /* 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) {

        struct timespec guac_vnc_connect_interval = {
            .tv_sec  =  GUAC_VNC_CONNECT_INTERVAL/1000,
            .tv_nsec = (GUAC_VNC_CONNECT_INTERVAL%1000)*1000000
        };

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

        /* Wait for given interval then retry */
        nanosleep(&guac_vnc_connect_interval, NULL);
        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(client, GUAC_LOG_INFO,
                    "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(client, GUAC_LOG_INFO,
                    "No available audio encoding. Sound disabled.");

    } /* end if audio enabled */
#endif

#ifdef ENABLE_COMMON_SSH
    guac_common_ssh_init(client);

    /* Connect via SSH if SFTP is enabled */
    if (strcmp(argv[IDX_ENABLE_SFTP], "true") == 0) {

        guac_client_log(client, GUAC_LOG_DEBUG,
                "Connecting via SSH for SFTP filesystem access.");

        guac_client_data->sftp_user =
            guac_common_ssh_create_user(argv[IDX_SFTP_USERNAME]);

        /* Import private key, if given */
        if (argv[IDX_SFTP_PRIVATE_KEY][0] != '\0') {

            guac_client_log(client, GUAC_LOG_DEBUG,
                    "Authenticating with private key.");

            /* Abort if private key cannot be read */
            if (guac_common_ssh_user_import_key(guac_client_data->sftp_user,
                        argv[IDX_SFTP_PRIVATE_KEY],
                        argv[IDX_SFTP_PASSPHRASE])) {
                guac_common_ssh_destroy_user(guac_client_data->sftp_user);
                return 1;
            }

        }

        /* Otherwise, use specified password */
        else {
            guac_client_log(client, GUAC_LOG_DEBUG,
                    "Authenticating with password.");
            guac_common_ssh_user_set_password(guac_client_data->sftp_user,
                    argv[IDX_SFTP_PASSWORD]);
        }

        /* Parse hostname - use VNC hostname by default */
        const char* sftp_hostname = argv[IDX_SFTP_HOSTNAME];
        if (sftp_hostname[0] == '\0')
            sftp_hostname = guac_client_data->hostname;

        /* Parse port, defaulting to standard SSH port */
        const char* sftp_port = argv[IDX_SFTP_PORT];
        if (sftp_port[0] == '\0')
            sftp_port = "22";

        /* Attempt SSH connection */
        guac_client_data->sftp_session =
            guac_common_ssh_create_session(client, sftp_hostname, sftp_port,
                    guac_client_data->sftp_user);

        /* Fail if SSH connection does not succeed */
        if (guac_client_data->sftp_session == NULL) {
            /* Already aborted within guac_common_ssh_create_session() */
            guac_common_ssh_destroy_user(guac_client_data->sftp_user);
            return 1;
        }

        /* Load and expose filesystem */
        guac_client_data->sftp_filesystem =
            guac_common_ssh_create_sftp_filesystem(
                    guac_client_data->sftp_session, "/");

        /* Abort if SFTP connection fails */
        if (guac_client_data->sftp_filesystem == NULL) {
            guac_common_ssh_destroy_session(guac_client_data->sftp_session);
            guac_common_ssh_destroy_user(guac_client_data->sftp_user);
            return 1;
        }

        /* Configure destination for basic uploads, if specified */
        if (argv[IDX_SFTP_DIRECTORY][0] != '\0')
            guac_common_ssh_sftp_set_upload_path(
                    guac_client_data->sftp_filesystem,
                    argv[IDX_SFTP_DIRECTORY]);

        /* Set file handler for basic uploads */
        client->file_handler = guac_vnc_sftp_file_handler;

        guac_client_log(client, GUAC_LOG_DEBUG,
                "SFTP connection succeeded.");

    }
#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 = guac_vnc_clipboard_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);

    /* Create default surface */
    guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER,
                                                                  rfb_client->width, rfb_client->height);
    return 0;

}
Exemplo n.º 9
0
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;

}
Exemplo n.º 10
0
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;

}