guac_stream* guac_sftp_download_file(guac_client* client, char* filename) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; guac_stream* stream; LIBSSH2_SFTP_HANDLE* file; /* Attempt to open file for reading */ file = libssh2_sftp_open(client_data->sftp_session, filename, LIBSSH2_FXF_READ, 0); if (file == NULL) { guac_client_log_error(client, "Unable to read file \"%s\": %s", filename, libssh2_sftp_last_error(client_data->sftp_session)); return NULL; } /* Allocate stream */ stream = guac_client_alloc_stream(client); stream->ack_handler = guac_sftp_ack_handler; stream->data = file; /* Send stream start, strip name */ filename = basename(filename); guac_protocol_send_file(client->socket, stream, "application/octet-stream", filename); guac_socket_flush(client->socket); return stream; }
int guac_sftp_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { /* Pull file from stream */ ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt write */ if (libssh2_sftp_write(file, data, length) == length) { guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } /* Inform of any errors */ else { guac_client_log_error(client, "Unable to write to file: %s", libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed", GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); guac_socket_flush(client->socket); } return 0; }
int vnc_guac_client_handle_messages(guac_client* client) { int wait_result; rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; wait_result = WaitForMessage(rfb_client, 1000000); if (wait_result < 0) { guac_client_log_error(client, "Error waiting for VNC server message\n"); return 1; } if (wait_result > 0) { if (!HandleRFBServerMessage(rfb_client)) { guac_client_log_error(client, "Error handling VNC server message\n"); return 1; } } return 0; }
void guac_sftp_set_upload_path(guac_client* client, char* path) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; int length = strnlen(path, GUAC_SFTP_MAX_PATH); /* Ignore requests which exceed maximum-allowed path */ if (length > GUAC_SFTP_MAX_PATH) { guac_client_log_error(client, "Submitted path exceeds limit of %i bytes", GUAC_SFTP_MAX_PATH); return; } /* Copy path */ memcpy(client_data->sftp_upload_path, path, length); }
int guac_sftp_end_handler(guac_client* client, guac_stream* stream) { /* Pull file from stream */ LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt to close file */ if (libssh2_sftp_close(file) == 0) { guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } else { guac_client_log_error(client, "Unable to close file"); guac_protocol_send_ack(client->socket, stream, "SFTP: Close failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); } return 0; }
int guac_sftp_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = libssh2_sftp_read(file, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) guac_protocol_send_blob(client->socket, stream, buffer, bytes_read); /* If EOF, send end */ else if (bytes_read == 0) { guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); } /* Otherwise, fail stream */ else { guac_client_log_error(client, "Error reading file: %s", libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); } guac_socket_flush(client->socket); } /* Otherwise, return stream to client */ else guac_client_free_stream(client, stream); return 0; }
void guac_rdp_process_cb_data_request(guac_client* client, RDP_CB_DATA_REQUEST_EVENT* event) { rdpChannels* channels = ((rdp_guac_client_data*) client->data)->rdp_inst->context->channels; /* If text requested, send clipboard text contents */ if (event->format == CB_FORMAT_TEXT) { /* Get clipboard data */ const char* clipboard = ((rdp_guac_client_data*) client->data)->clipboard; /* Create new data response */ RDP_CB_DATA_RESPONSE_EVENT* data_response = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new( CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL); /* Set data and length */ if (clipboard != NULL) { data_response->data = (UINT8*) strdup(clipboard); data_response->size = strlen(clipboard) + 1; } else { data_response->data = (UINT8*) strdup(""); data_response->size = 1; } /* Send response */ freerdp_channels_send_event(channels, (wMessage*) data_response); } /* Otherwise ... failure */ else guac_client_log_error(client, "Server requested unsupported clipboard data type"); }
static void __context_get_server_info_callback(pa_context* context, const pa_server_info* info, void* data) { guac_client* client = (guac_client*) data; /* If no default sink, cannot continue */ if (info->default_sink_name == NULL) { guac_client_log_error(client, "No default sink. Cannot stream audio."); return; } guac_client_log_info(client, "Will use default sink: \"%s\"", info->default_sink_name); /* Wait for default sink information */ pa_operation_unref( pa_context_get_sink_info_by_name(context, info->default_sink_name, __context_get_sink_info_callback, client)); }
void guac_rdp_process_cb_data_response(guac_client* client, RDP_CB_DATA_RESPONSE_EVENT* event) { /* Received clipboard data */ if (event->data[event->size - 1] == '\0') { /* Free existing data */ free(((rdp_guac_client_data*) client->data)->clipboard); /* Store clipboard data */ ((rdp_guac_client_data*) client->data)->clipboard = strdup((char*) event->data); /* Send clipboard data */ guac_protocol_send_clipboard(client->socket, (char*) event->data); } else guac_client_log_error(client, "Clipboard data missing null terminator"); }
int guac_sftp_file_handler(guac_client* client, guac_stream* stream, char* mimetype, char* filename) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; char fullpath[GUAC_SFTP_MAX_PATH]; LIBSSH2_SFTP_HANDLE* file; int i; /* Ensure filename is a valid filename and not a path */ if (!__ssh_guac_valid_filename(filename)) { guac_protocol_send_ack(client->socket, stream, "SFTP: Illegal filename", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); guac_socket_flush(client->socket); return 0; } /* Copy upload path, append trailing slash */ for (i=0; i<GUAC_SFTP_MAX_PATH; i++) { char c = client_data->sftp_upload_path[i]; if (c == '\0') { fullpath[i++] = '/'; break; } fullpath[i] = c; } /* Append filename */ for (; i<GUAC_SFTP_MAX_PATH; i++) { char c = *(filename++); if (c == '\0') break; fullpath[i] = c; } /* If path + filename exceeds max length, abort */ if (i == GUAC_SFTP_MAX_PATH) { guac_protocol_send_ack(client->socket, stream, "SFTP: Name too long", GUAC_PROTOCOL_STATUS_CLIENT_OVERRUN); guac_socket_flush(client->socket); return 0; } /* Terminate path string */ fullpath[i] = '\0'; /* Open file via SFTP */ file = libssh2_sftp_open(client_data->sftp_session, fullpath, LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, S_IRUSR | S_IWUSR); /* Inform of status */ if (file != NULL) { guac_protocol_send_ack(client->socket, stream, "SFTP: File opened", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } else { guac_client_log_error(client, "Unable to open file \"%s\": %s", fullpath, libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND); guac_socket_flush(client->socket); } /* Set handlers for file stream */ stream->blob_handler = guac_sftp_blob_handler; stream->end_handler = guac_sftp_end_handler; /* Store file within stream */ stream->data = file; return 0; }
void* ssh_client_thread(void* data) { guac_client* client = (guac_client*) data; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; char name[1024]; guac_socket* socket = client->socket; char buffer[8192]; int bytes_read = -1234; int socket_fd; int stdout_fd = client_data->term->stdout_pipe_fd[1]; pthread_t input_thread; libssh2_init(0); /* Get username */ if (client_data->username[0] == 0) prompt(client, "Login as: ", client_data->username, sizeof(client_data->username), true); /* Send new name */ snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname); guac_protocol_send_name(socket, name); /* If key specified, import */ if (client_data->key_base64[0] != 0) { /* Attempt to read key without passphrase */ client_data->key = ssh_key_alloc(client_data->key_base64, strlen(client_data->key_base64), ""); /* On failure, attempt with passphrase */ if (client_data->key == NULL) { /* Prompt for passphrase if missing */ if (client_data->key_passphrase[0] == 0) prompt(client, "Key passphrase: ", client_data->key_passphrase, sizeof(client_data->key_passphrase), false); /* Import key with passphrase */ client_data->key = ssh_key_alloc(client_data->key_base64, strlen(client_data->key_base64), client_data->key_passphrase); /* If still failing, give up */ if (client_data->key == NULL) { guac_client_log_error(client, "Auth key import failed."); return NULL; } } /* end decrypt key with passphrase */ /* Success */ guac_client_log_info(client, "Auth key successfully imported."); } /* end if key given */ /* Otherwise, get password if not provided */ else if (client_data->password[0] == 0) prompt(client, "Password: "******"\x1B[H\x1B[J", 6); /* Open SSH session */ client_data->session = __guac_ssh_create_session(client, &socket_fd); if (client_data->session == NULL) { /* Already aborted within __guac_ssh_create_session() */ return NULL; } /* Open channel for terminal */ client_data->term_channel = libssh2_channel_open_session(client_data->session); if (client_data->term_channel == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel."); return NULL; } #ifdef ENABLE_SSH_AGENT /* Start SSH agent forwarding, if enabled */ if (client_data->enable_agent) { libssh2_session_callback_set(client_data->session, LIBSSH2_CALLBACK_AUTH_AGENT, (void*) ssh_auth_agent_callback); /* Request agent forwarding */ if (libssh2_channel_request_auth_agent(client_data->term_channel)) guac_client_log_error(client, "Agent forwarding request failed"); else guac_client_log_info(client, "Agent forwarding enabled."); } client_data->auth_agent = NULL; #endif /* Start SFTP session as well, if enabled */ if (client_data->enable_sftp) { /* Create SSH session specific for SFTP */ guac_client_log_info(client, "Reconnecting for SFTP..."); client_data->sftp_ssh_session = __guac_ssh_create_session(client, NULL); if (client_data->sftp_ssh_session == NULL) { /* Already aborted within __guac_ssh_create_session() */ return NULL; } /* Request SFTP */ client_data->sftp_session = libssh2_sftp_init(client_data->sftp_ssh_session); if (client_data->sftp_session == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to start SFTP session."); return NULL; } /* Set file handler */ client->file_handler = guac_sftp_file_handler; guac_client_log_info(client, "SFTP session initialized"); } /* Request PTY */ if (libssh2_channel_request_pty_ex(client_data->term_channel, "linux", sizeof("linux")-1, NULL, 0, client_data->term->term_width, client_data->term->term_height, 0, 0)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY."); return NULL; } /* Request shell */ if (libssh2_channel_shell(client_data->term_channel)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY."); return NULL; } /* Logged in */ guac_client_log_info(client, "SSH connection successful."); /* Start input thread */ if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread"); return NULL; } /* Set non-blocking */ libssh2_session_set_blocking(client_data->session, 0); /* While data available, write to terminal */ bytes_read = 0; while (!libssh2_channel_eof(client_data->term_channel)) { /* Track total amount of data read */ int total_read = 0; /* Read terminal data */ bytes_read = libssh2_channel_read(client_data->term_channel, buffer, sizeof(buffer)); /* Attempt to write data received. Exit on failure. */ if (bytes_read > 0) { int written = guac_terminal_write_all(stdout_fd, buffer, bytes_read); if (written < 0) break; total_read += bytes_read; } else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) break; #ifdef ENABLE_SSH_AGENT /* If agent open, handle any agent packets */ if (client_data->auth_agent != NULL) { bytes_read = ssh_auth_agent_read(client_data->auth_agent); if (bytes_read > 0) total_read += bytes_read; else if (bytes_read < 0 && bytes_read != LIBSSH2_ERROR_EAGAIN) client_data->auth_agent = NULL; } #endif /* Wait for more data if reads turn up empty */ if (total_read == 0) { fd_set fds; struct timeval timeout; FD_ZERO(&fds); FD_SET(socket_fd, &fds); /* Wait for one second */ timeout.tv_sec = 1; timeout.tv_usec = 0; if (select(socket_fd+1, &fds, NULL, NULL, &timeout) < 0) break; } } /* Kill client and Wait for input thread to die */ guac_client_stop(client); pthread_join(input_thread, NULL); guac_client_log_info(client, "SSH connection ended."); return NULL; }
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; }
boolean rdp_freerdp_pre_connect(freerdp* instance) { rdpContext* context = instance->context; guac_client* client = ((rdp_freerdp_context*) context)->client; rdpChannels* channels = context->channels; rdpBitmap* bitmap; rdpGlyph* glyph; rdpPointer* pointer; rdpPrimaryUpdate* primary; CLRCONV* clrconv; int i; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; /* Load clipboard plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "cliprdr", NULL)) guac_client_log_error(client, "Failed to load cliprdr plugin."); /* If audio enabled, choose an encoder */ if (guac_client_data->audio_enabled) { /* Choose an encoding */ for (i=0; client->info.audio_mimetypes[i] != NULL; i++) { const char* mimetype = client->info.audio_mimetypes[i]; #ifdef ENABLE_OGG /* If Ogg is supported, done. */ if (strcmp(mimetype, ogg_encoder->mimetype) == 0) { guac_client_log_info(client, "Loading Ogg Vorbis encoder."); guac_client_data->audio = audio_stream_alloc(client, ogg_encoder); break; } #endif /* If wav is supported, done. */ if (strcmp(mimetype, wav_encoder->mimetype) == 0) { guac_client_log_info(client, "Loading wav encoder."); guac_client_data->audio = audio_stream_alloc(client, wav_encoder); break; } } /* If an encoding is available, load the sound plugin */ if (guac_client_data->audio != NULL) { /* Load sound plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guac_rdpsnd", guac_client_data->audio)) guac_client_log_error(client, "Failed to load guac_rdpsnd plugin."); } else guac_client_log_info(client, "No available audio encoding. Sound disabled."); } /* end if audio enabled */ /* If printing enabled, load rdpdr */ if (guac_client_data->printing_enabled) { /* Load RDPDR plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, "guac_rdpdr", client)) guac_client_log_error(client, "Failed to load guac_rdpdr plugin."); } /* end if printing enabled */ /* Init color conversion structure */ clrconv = xnew(CLRCONV); clrconv->alpha = 1; clrconv->invert = 0; clrconv->rgb555 = 0; clrconv->palette = xnew(rdpPalette); ((rdp_freerdp_context*) context)->clrconv = clrconv; /* Init FreeRDP cache */ instance->context->cache = cache_new(instance->settings); /* Set up bitmap handling */ bitmap = xnew(rdpBitmap); bitmap->size = sizeof(guac_rdp_bitmap); bitmap->New = guac_rdp_bitmap_new; bitmap->Free = guac_rdp_bitmap_free; bitmap->Paint = guac_rdp_bitmap_paint; bitmap->Decompress = guac_rdp_bitmap_decompress; bitmap->SetSurface = guac_rdp_bitmap_setsurface; graphics_register_bitmap(context->graphics, bitmap); xfree(bitmap); /* Set up glyph handling */ glyph = xnew(rdpGlyph); glyph->size = sizeof(guac_rdp_glyph); glyph->New = guac_rdp_glyph_new; glyph->Free = guac_rdp_glyph_free; glyph->Draw = guac_rdp_glyph_draw; glyph->BeginDraw = guac_rdp_glyph_begindraw; glyph->EndDraw = guac_rdp_glyph_enddraw; graphics_register_glyph(context->graphics, glyph); xfree(glyph); /* Set up pointer handling */ pointer = xnew(rdpPointer); pointer->size = sizeof(guac_rdp_pointer); pointer->New = guac_rdp_pointer_new; pointer->Free = guac_rdp_pointer_free; pointer->Set = guac_rdp_pointer_set; #ifdef HAVE_RDPPOINTER_SETNULL pointer->SetNull = guac_rdp_pointer_set_null; #endif #ifdef HAVE_RDPPOINTER_SETDEFAULT pointer->SetDefault = guac_rdp_pointer_set_default; #endif graphics_register_pointer(context->graphics, pointer); xfree(pointer); /* Set up GDI */ instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->Palette = guac_rdp_gdi_palette_update; instance->update->SetBounds = guac_rdp_gdi_set_bounds; primary = instance->update->primary; primary->DstBlt = guac_rdp_gdi_dstblt; primary->PatBlt = guac_rdp_gdi_patblt; primary->ScrBlt = guac_rdp_gdi_scrblt; primary->MemBlt = guac_rdp_gdi_memblt; primary->OpaqueRect = guac_rdp_gdi_opaquerect; pointer_cache_register_callbacks(instance->update); glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); bitmap_cache_register_callbacks(instance->update); offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); /* Init channels (pre-connect) */ if (freerdp_channels_pre_connect(channels, instance)) { guac_protocol_send_error(client->socket, "Error initializing RDP client channel manager"); guac_socket_flush(client->socket); return false; } return true; }
int guac_client_init(guac_client* client, int argc, char** argv) { guac_socket* socket = client->socket; ssh_guac_client_data* client_data = malloc(sizeof(ssh_guac_client_data)); /* Init client data */ client->data = client_data; client_data->mod_alt = client_data->mod_ctrl = client_data->mod_shift = 0; client_data->clipboard_data = NULL; client_data->term_channel = NULL; if (argc != SSH_ARGS_COUNT) { guac_client_log_error(client, "Wrong number of arguments"); return -1; } /* Read parameters */ strcpy(client_data->hostname, argv[IDX_HOSTNAME]); strcpy(client_data->username, argv[IDX_USERNAME]); strcpy(client_data->password, argv[IDX_PASSWORD]); /* Read font name */ if (argv[IDX_FONT_NAME][0] != 0) strcpy(client_data->font_name, argv[IDX_FONT_NAME]); else strcpy(client_data->font_name, GUAC_SSH_DEFAULT_FONT_NAME ); /* Read font size */ if (argv[IDX_FONT_SIZE][0] != 0) client_data->font_size = atoi(argv[IDX_FONT_SIZE]); else client_data->font_size = GUAC_SSH_DEFAULT_FONT_SIZE; /* Read port */ if (argv[IDX_PORT][0] != 0) client_data->port = atoi(argv[IDX_PORT]); else client_data->port = GUAC_SSH_DEFAULT_PORT; /* Create terminal */ client_data->term = guac_terminal_create(client, client_data->font_name, client_data->font_size, client->info.optimal_width, client->info.optimal_height); /* Fail if terminal init failed */ if (client_data->term == NULL) { guac_error = GUAC_STATUS_BAD_STATE; guac_error_message = "Terminal initialization failed"; return -1; } /* Set up I-bar pointer */ client_data->ibar_cursor = guac_ssh_create_ibar(client); /* Set up blank pointer */ client_data->blank_cursor = guac_ssh_create_blank(client); /* Send initial name */ guac_protocol_send_name(socket, client_data->hostname); /* Initialize pointer */ client_data->current_cursor = client_data->blank_cursor; guac_ssh_set_cursor(client, client_data->current_cursor); guac_socket_flush(socket); /* Set basic handlers */ client->handle_messages = ssh_guac_client_handle_messages; client->clipboard_handler = ssh_guac_client_clipboard_handler; client->key_handler = ssh_guac_client_key_handler; client->mouse_handler = ssh_guac_client_mouse_handler; client->size_handler = ssh_guac_client_size_handler; client->free_handler = ssh_guac_client_free_handler; /* Start client thread */ if (pthread_create(&(client_data->client_thread), NULL, ssh_client_thread, (void*) client)) { guac_client_log_error(client, "Unable to SSH client thread"); return -1; } /* Success */ return 0; }