static int wlfreerdp_run(freerdp* instance) { DWORD count; HANDLE handles[64]; DWORD status; if (!freerdp_connect(instance)) { printf("Failed to connect\n"); return -1; } handle_uwac_events(instance, g_display); while (!freerdp_shall_disconnect(instance)) { handles[0] = g_displayHandle; count = freerdp_get_event_handles(instance->context, &handles[1], 63); if (!count) { printf("Failed to get FreeRDP file descriptor\n"); break; } status = WaitForMultipleObjects(count+1, handles, FALSE, INFINITE); if (WAIT_FAILED == status) { printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__); break; } if (!handle_uwac_events(instance, g_display)) { printf("error handling UWAC events\n"); break; } //if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) { if (freerdp_check_event_handles(instance->context) != TRUE) { printf("Failed to check FreeRDP file descriptor\n"); break; } //} } freerdp_channels_disconnect(instance->context->channels, instance); freerdp_disconnect(instance); return 0; }
static DWORD WINAPI tf_client_thread_proc(LPVOID arg) { freerdp* instance = (freerdp*)arg; DWORD nCount; DWORD status; HANDLE handles[64]; if (!freerdp_connect(instance)) { WLog_ERR(TAG, "connection failure"); return 0; } while (!freerdp_shall_disconnect(instance)) { nCount = freerdp_get_event_handles(instance->context, &handles[0], 64); if (nCount == 0) { WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__); break; } status = WaitForMultipleObjects(nCount, handles, FALSE, 100); if (status == WAIT_FAILED) { WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %"PRIu32"", __FUNCTION__, status); break; } if (!freerdp_check_event_handles(instance->context)) { if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS) WLog_ERR(TAG, "Failed to check FreeRDP event handles"); break; } } freerdp_disconnect(instance); ExitThread(0); return 0; }
static void* tf_client_thread_proc(freerdp* instance) { DWORD nCount; DWORD status; HANDLE handles[64]; if (!freerdp_connect(instance)) { WLog_ERR(TAG, "connection failure"); return NULL; } while (!freerdp_shall_disconnect(instance)) { nCount = freerdp_get_event_handles(instance->context, &handles[0], 64); if (nCount == 0) { WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__); break; } status = WaitForMultipleObjects(nCount, handles, FALSE, 100); if (status == WAIT_FAILED) { WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %lu", __FUNCTION__, (unsigned long) status); break; } if (!freerdp_check_event_handles(instance->context)) { WLog_ERR(TAG, "Failed to check FreeRDP event handles"); break; } } freerdp_disconnect(instance); ExitThread(0); return NULL; }
static int runInstance(int argc, char* argv[], freerdp** inst) { int rc = -1; freerdp* instance = freerdp_new(); if (!instance) goto finish; if (inst) *inst = instance; if (!freerdp_context_new(instance)) goto finish; if (freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE) < 0) goto finish; if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) goto finish; if (s_sync) { if (!SetEvent(s_sync)) goto finish; } rc = 1; if (!freerdp_connect(instance)) goto finish; rc = 2; if (!freerdp_disconnect(instance)) goto finish; rc = 0; finish: freerdp_context_free(instance); freerdp_free(instance); return rc; }
static void* android_thread_func(void* param) { DWORD status = ERROR_BAD_ARGUMENTS; freerdp* instance = param; WLog_DBG(TAG, "Start..."); if (!instance || !instance->context) goto fail; if (freerdp_client_start(instance->context) != CHANNEL_RC_OK) goto fail; WLog_DBG(TAG, "Connect..."); if (!freerdp_connect(instance)) status = GetLastError(); else { status = android_freerdp_run(instance); WLog_DBG(TAG, "Disonnect..."); if (!freerdp_disconnect(instance)) status = GetLastError(); } WLog_DBG(TAG, "Stop..."); if (freerdp_client_stop(instance->context) != CHANNEL_RC_OK) goto fail; fail: WLog_DBG(TAG, "Session ended with %08lX", status); if (status == CHANNEL_RC_OK) freerdp_callback("OnDisconnected", "(I)V", instance); else freerdp_callback("OnConnectionFailure", "(I)V", instance); WLog_DBG(TAG, "Quit."); ExitThread(status); return NULL; }
static int wlfreerdp_run(freerdp* instance) { DWORD count; HANDLE handles[64]; DWORD status; if (!freerdp_connect(instance)) { printf("Failed to connect\n"); return -1; } while (!freerdp_shall_disconnect(instance)) { count = freerdp_get_event_handles(instance->context, handles, 64); if (!count) { printf("Failed to get FreeRDP file descriptor\n"); break; } status = WaitForMultipleObjects(count, handles, FALSE, INFINITE); if (WAIT_FAILED == status) { printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__); break; } if (freerdp_check_event_handles(instance->context) != TRUE) { printf("Failed to check FreeRDP file descriptor\n"); break; } } freerdp_channels_disconnect(instance->context->channels, instance); freerdp_disconnect(instance); return 0; }
static DWORD WINAPI shw_client_thread(LPVOID arg) { int index; int rcount; int wcount; BOOL bSuccess; void* rfds[32]; void* wfds[32]; int fds_count; HANDLE fds[64]; shwContext* shw; rdpContext* context; rdpChannels* channels; freerdp* instance = (freerdp*) arg; ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); context = (rdpContext*) instance->context; shw = (shwContext*) context; bSuccess = freerdp_connect(instance); WLog_INFO(TAG, "freerdp_connect: %d", bSuccess); if (!bSuccess) { ExitThread(0); return 0; } channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); break; } if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get channels file descriptor"); break; } fds_count = 0; for (index = 0; index < rcount; index++) fds[fds_count++] = rfds[index]; for (index = 0; index < wcount; index++) fds[fds_count++] = wfds[index]; if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) { WLog_ERR(TAG, "MsgWaitForMultipleObjects failure: 0x%08lX", GetLastError()); break; } if (!freerdp_check_fds(instance)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } if (freerdp_shall_disconnect(instance)) { break; } if (!freerdp_channels_check_fds(channels, instance)) { WLog_ERR(TAG, "Failed to check channels file descriptor"); break; } } freerdp_free(instance); ExitThread(0); return 0; }
/** * Connects to an RDP server as described by the guac_rdp_settings structure * associated with the given client, allocating and freeing all objects * directly related to the RDP connection. It is expected that all objects * which are independent of FreeRDP's state (the clipboard, display update * management, etc.) will already be allocated and associated with the * guac_rdp_client associated with the given guac_client. This function blocks * for the duration of the RDP session, returning only after the session has * completely disconnected. * * @param client * The guac_client associated with the RDP settings describing the * connection that should be established. * * @return * Zero if the connection successfully terminated and a reconnect is * desired, non-zero if an error occurs or the connection was disconnected * and a reconnect is NOT desired. */ static int guac_rdp_handle_connection(guac_client* client) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Init random number generator */ srandom(time(NULL)); /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path); } /* Create display */ rdp_client->display = guac_common_display_alloc(client, rdp_client->settings->width, rdp_client->settings->height); rdp_client->current_surface = rdp_client->display->default_surface; rdp_client->requested_clipboard_format = CB_FORMAT_TEXT; rdp_client->available_svc = guac_common_list_alloc(); #ifdef HAVE_FREERDP_CHANNELS_GLOBAL_INIT freerdp_channels_global_init(); #endif /* Init client */ freerdp* rdp_inst = freerdp_new(); rdp_inst->PreConnect = rdp_freerdp_pre_connect; rdp_inst->PostConnect = rdp_freerdp_post_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; rdp_inst->ReceiveChannelData = __guac_receive_channel_data; /* Allocate FreeRDP context */ #ifdef LEGACY_FREERDP rdp_inst->context_size = sizeof(rdp_freerdp_context); #else rdp_inst->ContextSize = sizeof(rdp_freerdp_context); #endif rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new; rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free; freerdp_context_new(rdp_inst); ((rdp_freerdp_context*) rdp_inst->context)->client = client; /* Load keymap into client */ rdp_client->keyboard = guac_rdp_keyboard_alloc(client, settings->server_layout); /* Send connection name */ guac_protocol_send_name(client->socket, settings->hostname); /* Set default pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); /* Push desired settings to FreeRDP */ guac_rdp_push_settings(settings, rdp_inst); /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Error connecting to RDP server"); return 1; } /* Connection complete */ rdp_client->rdp_inst = rdp_inst; rdpChannels* channels = rdp_inst->context->channels; guac_timestamp last_frame_end = guac_timestamp_current(); /* Signal that reconnect has been completed */ guac_rdp_disp_reconnect_complete(rdp_client->disp); /* Handle messages from RDP server while client is running */ while (client->state == GUAC_CLIENT_RUNNING && !guac_rdp_disp_reconnect_needed(rdp_client->disp)) { /* Update remote display size */ pthread_mutex_lock(&(rdp_client->rdp_lock)); guac_rdp_disp_update_size(rdp_client->disp, settings, rdp_inst); pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Wait for data and construct a reasonable frame */ int wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_START_TIMEOUT); if (wait_result > 0) { int processing_lag = guac_client_get_processing_lag(client); guac_timestamp frame_start = guac_timestamp_current(); /* Read server messages until frame is built */ do { guac_timestamp frame_end; int frame_remaining; pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Check the libfreerdp fds */ if (!freerdp_check_fds(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error handling RDP file descriptors"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } /* Check channel fds */ if (!freerdp_channels_check_fds(channels, rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error handling RDP channel file descriptors"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } /* Check for channel events */ wMessage* event = freerdp_channels_pop_event(channels); if (event) { /* Handle channel events (clipboard and RAIL) */ #ifdef LEGACY_EVENT if (event->event_class == CliprdrChannel_Class) guac_rdp_process_cliprdr_event(client, event); else if (event->event_class == RailChannel_Class) guac_rdp_process_rail_event(client, event); #else if (GetMessageClass(event->id) == CliprdrChannel_Class) guac_rdp_process_cliprdr_event(client, event); else if (GetMessageClass(event->id) == RailChannel_Class) guac_rdp_process_rail_event(client, event); #endif freerdp_event_free(event); } /* Handle RDP disconnect */ if (freerdp_shall_disconnect(rdp_inst)) { guac_client_stop(client); guac_client_log(client, GUAC_LOG_INFO, "RDP server closed connection"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Calculate time remaining in frame */ frame_end = guac_timestamp_current(); frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION - frame_end; /* Calculate time that client needs to catch up */ int time_elapsed = frame_end - last_frame_end; int required_wait = processing_lag - time_elapsed; /* Increase the duration of this frame if client is lagging */ if (required_wait > GUAC_RDP_FRAME_TIMEOUT) wait_result = rdp_guac_client_wait_for_messages(client, required_wait); /* Wait again if frame remaining */ else if (frame_remaining > 0) wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_TIMEOUT); else break; } while (wait_result > 0); /* Record end of frame, excluding server-side rendering time (we * assume server-side rendering time will be consistent between any * two subsequent frames, and that this time should thus be * excluded from the required wait period of the next frame). */ last_frame_end = frame_start; } /* If an error occurred, fail */ if (wait_result < 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Connection closed."); /* Flush frame */ guac_common_display_flush(rdp_client->display); guac_client_end_frame(client); guac_socket_flush(client->socket); } pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Disconnect client and channels */ freerdp_channels_close(channels, rdp_inst); freerdp_channels_free(channels); freerdp_disconnect(rdp_inst); /* Clean up RDP client context */ freerdp_clrconv_free(((rdp_freerdp_context*) rdp_inst->context)->clrconv); cache_free(rdp_inst->context->cache); freerdp_context_free(rdp_inst); /* Clean up RDP client */ freerdp_free(rdp_inst); rdp_client->rdp_inst = NULL; /* Free SVC list */ guac_common_list_free(rdp_client->available_svc); /* Free RDP keyboard state */ guac_rdp_keyboard_free(rdp_client->keyboard); /* Free display */ guac_common_display_free(rdp_client->display); pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Client is now disconnected */ guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected"); return 0; }
/** * Waits for messages from the RDP server for the given number of microseconds. * * @param client * The client associated with the current RDP session. * * @param timeout_usecs * The maximum amount of time to wait, in microseconds. * * @return * A positive value if messages are ready, zero if the specified timeout * period elapsed, or a negative value if an error occurs. */ static int rdp_guac_client_wait_for_messages(guac_client* client, int timeout_usecs) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; freerdp* rdp_inst = rdp_client->rdp_inst; rdpChannels* channels = rdp_inst->context->channels; int result; int index; int max_fd, fd; void* read_fds[32]; void* write_fds[32]; int read_count = 0; int write_count = 0; fd_set rfds, wfds; struct timeval timeout = { .tv_sec = 0, .tv_usec = timeout_usecs }; /* Get RDP fds */ if (!freerdp_get_fds(rdp_inst, read_fds, &read_count, write_fds, &write_count)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to read RDP file descriptors."); return -1; } /* Get channel fds */ if (!freerdp_channels_get_fds(channels, rdp_inst, read_fds, &read_count, write_fds, &write_count)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to read RDP channel file descriptors."); return -1; } /* Construct read fd_set */ max_fd = 0; FD_ZERO(&rfds); for (index = 0; index < read_count; index++) { fd = (int)(long) (read_fds[index]); if (fd > max_fd) max_fd = fd; FD_SET(fd, &rfds); } /* Construct write fd_set */ FD_ZERO(&wfds); for (index = 0; index < write_count; index++) { fd = (int)(long) (write_fds[index]); if (fd > max_fd) max_fd = fd; FD_SET(fd, &wfds); } /* If no file descriptors, error */ if (max_fd == 0) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "No file descriptors associated with RDP connection."); return -1; } /* Wait for all RDP file descriptors */ result = select(max_fd + 1, &rfds, &wfds, NULL, &timeout); if (result < 0) { /* If error ignorable, pretend timout occurred */ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EINTR) return 0; /* Otherwise, return as error */ guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error waiting for file descriptor."); return -1; } /* Return wait result */ return result; } /** * Connects to an RDP server as described by the guac_rdp_settings structure * associated with the given client, allocating and freeing all objects * directly related to the RDP connection. It is expected that all objects * which are independent of FreeRDP's state (the clipboard, display update * management, etc.) will already be allocated and associated with the * guac_rdp_client associated with the given guac_client. This function blocks * for the duration of the RDP session, returning only after the session has * completely disconnected. * * @param client * The guac_client associated with the RDP settings describing the * connection that should be established. * * @return * Zero if the connection successfully terminated and a reconnect is * desired, non-zero if an error occurs or the connection was disconnected * and a reconnect is NOT desired. */ static int guac_rdp_handle_connection(guac_client* client) { guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; guac_rdp_settings* settings = rdp_client->settings; /* Init random number generator */ srandom(time(NULL)); /* Set up screen recording, if requested */ if (settings->recording_path != NULL) { guac_common_recording_create(client, settings->recording_path, settings->recording_name, settings->create_recording_path); } /* Create display */ rdp_client->display = guac_common_display_alloc(client, rdp_client->settings->width, rdp_client->settings->height); rdp_client->current_surface = rdp_client->display->default_surface; rdp_client->requested_clipboard_format = CB_FORMAT_TEXT; rdp_client->available_svc = guac_common_list_alloc(); #ifdef HAVE_FREERDP_CHANNELS_GLOBAL_INIT freerdp_channels_global_init(); #endif /* Init client */ freerdp* rdp_inst = freerdp_new(); rdp_inst->PreConnect = rdp_freerdp_pre_connect; rdp_inst->PostConnect = rdp_freerdp_post_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; rdp_inst->ReceiveChannelData = __guac_receive_channel_data; /* Allocate FreeRDP context */ #ifdef LEGACY_FREERDP rdp_inst->context_size = sizeof(rdp_freerdp_context); #else rdp_inst->ContextSize = sizeof(rdp_freerdp_context); #endif rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new; rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free; freerdp_context_new(rdp_inst); ((rdp_freerdp_context*) rdp_inst->context)->client = client; /* Load keymap into client */ __guac_rdp_client_load_keymap(client, settings->server_layout); /* Send connection name */ guac_protocol_send_name(client->socket, settings->hostname); /* Set default pointer */ guac_common_cursor_set_pointer(rdp_client->display->cursor); /* Push desired settings to FreeRDP */ guac_rdp_push_settings(settings, rdp_inst); /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Error connecting to RDP server"); return 1; } /* Connection complete */ rdp_client->rdp_inst = rdp_inst; rdpChannels* channels = rdp_inst->context->channels; guac_timestamp last_frame_end = guac_timestamp_current(); /* Signal that reconnect has been completed */ guac_rdp_disp_reconnect_complete(rdp_client->disp); /* Handle messages from RDP server while client is running */ while (client->state == GUAC_CLIENT_RUNNING && !guac_rdp_disp_reconnect_needed(rdp_client->disp)) { /* Update remote display size */ pthread_mutex_lock(&(rdp_client->rdp_lock)); guac_rdp_disp_update_size(rdp_client->disp, settings, rdp_inst); pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Wait for data and construct a reasonable frame */ int wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_START_TIMEOUT); if (wait_result > 0) { int processing_lag = guac_client_get_processing_lag(client); guac_timestamp frame_start = guac_timestamp_current(); /* Read server messages until frame is built */ do { guac_timestamp frame_end; int frame_remaining; pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Check the libfreerdp fds */ if (!freerdp_check_fds(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error handling RDP file descriptors"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } /* Check channel fds */ if (!freerdp_channels_check_fds(channels, rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error handling RDP channel file descriptors"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } /* Check for channel events */ wMessage* event = freerdp_channels_pop_event(channels); if (event) { /* Handle channel events (clipboard and RAIL) */ #ifdef LEGACY_EVENT if (event->event_class == CliprdrChannel_Class) guac_rdp_process_cliprdr_event(client, event); else if (event->event_class == RailChannel_Class) guac_rdp_process_rail_event(client, event); #else if (GetMessageClass(event->id) == CliprdrChannel_Class) guac_rdp_process_cliprdr_event(client, event); else if (GetMessageClass(event->id) == RailChannel_Class) guac_rdp_process_rail_event(client, event); #endif freerdp_event_free(event); } /* Handle RDP disconnect */ if (freerdp_shall_disconnect(rdp_inst)) { guac_client_stop(client); guac_client_log(client, GUAC_LOG_INFO, "RDP server closed connection"); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 1; } pthread_mutex_unlock(&(rdp_client->rdp_lock)); /* Calculate time remaining in frame */ frame_end = guac_timestamp_current(); frame_remaining = frame_start + GUAC_RDP_FRAME_DURATION - frame_end; /* Calculate time that client needs to catch up */ int time_elapsed = frame_end - last_frame_end; int required_wait = processing_lag - time_elapsed; /* Increase the duration of this frame if client is lagging */ if (required_wait > GUAC_RDP_FRAME_TIMEOUT) wait_result = rdp_guac_client_wait_for_messages(client, required_wait*1000); /* Wait again if frame remaining */ else if (frame_remaining > 0) wait_result = rdp_guac_client_wait_for_messages(client, GUAC_RDP_FRAME_TIMEOUT*1000); else break; } while (wait_result > 0); } /* If an error occurred, fail */ if (wait_result < 0) guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Connection closed."); /* End of frame */ guac_common_display_flush(rdp_client->display); guac_client_end_frame(client); guac_socket_flush(client->socket); /* Record end of frame */ last_frame_end = guac_timestamp_current(); } /* Kill client and finish connection */ guac_client_stop(client); guac_client_log(client, GUAC_LOG_INFO, "Internal RDP client disconnected"); pthread_mutex_lock(&(rdp_client->rdp_lock)); /* Disconnect client and channels */ freerdp_channels_close(channels, rdp_inst); freerdp_channels_free(channels); freerdp_disconnect(rdp_inst); /* Clean up RDP client context */ freerdp_clrconv_free(((rdp_freerdp_context*) rdp_inst->context)->clrconv); cache_free(rdp_inst->context->cache); freerdp_context_free(rdp_inst); /* Clean up RDP client */ freerdp_free(rdp_inst); rdp_client->rdp_inst = NULL; /* Free SVC list */ guac_common_list_free(rdp_client->available_svc); /* Free display */ guac_common_display_free(rdp_client->display); pthread_mutex_unlock(&(rdp_client->rdp_lock)); return 0; }
int tfreerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; rdpChannels* channels; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); channels = instance->context->channels; freerdp_connect(instance); while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("tfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } tf_process_channel_event(channels, instance); } freerdp_channels_close(channels, instance); freerdp_channels_free(channels); freerdp_free(instance); return 0; }
static int android_freerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; int fd_input_event; HANDLE input_event = NULL; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; int select_status; struct timeval timeout; const rdpSettings* settings = instance->context->settings; HANDLE input_thread = NULL; HANDLE channels_thread = NULL; BOOL async_input = settings->AsyncInput; BOOL async_channels = settings->AsyncChannels; BOOL async_transport = settings->AsyncTransport; DEBUG_ANDROID("AsyncUpdate=%d", settings->AsyncUpdate); DEBUG_ANDROID("AsyncInput=%d", settings->AsyncInput); DEBUG_ANDROID("AsyncChannels=%d", settings->AsyncChannels); DEBUG_ANDROID("AsyncTransport=%d", settings->AsyncTransport); memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (!freerdp_connect(instance)) { freerdp_callback("OnConnectionFailure", "(I)V", instance); return 0; } if (async_input) { if (!(input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) jni_input_thread, instance, 0, NULL))) { DEBUG_ANDROID("Failed to create async input thread\n"); goto disconnect; } } if (async_channels) { if (!(channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) jni_channels_thread, instance, 0, NULL))) { DEBUG_ANDROID("Failed to create async channels thread\n"); goto disconnect; } } ((androidContext*)instance->context)->is_connected = TRUE; while (!freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; if (!async_transport) { if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n"); break; } } if (!async_channels) { if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get channel manager file descriptor\n"); break; } } if (!async_input) { if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get android file descriptor\n"); break; } } else { input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); fd_input_event = GetEventFileDescriptor(input_event); rfds[rcount++] = (void*) (long) fd_input_event; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; timeout.tv_sec = 1; timeout.tv_usec = 0; select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); if (select_status == 0) continue; else if (select_status == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { DEBUG_ANDROID("android_run: select failed\n"); break; } } if (freerdp_shall_disconnect(instance)) break; if (!async_transport) { if (freerdp_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n"); break; } } if (!async_input) { if (android_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check android file descriptor\n"); break; } } else if (input_event) { if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0) { if (!freerdp_message_queue_process_pending_messages(instance, FREERDP_INPUT_MESSAGE_QUEUE)) { DEBUG_ANDROID("User Disconnect"); break; } } } if (!async_channels) { if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE) { DEBUG_ANDROID("Failed to check channel manager file descriptor\n"); break; } } } disconnect: DEBUG_ANDROID("Prepare shutdown..."); // issue another OnDisconnecting here in case the disconnect was initiated by the server and not our client freerdp_callback("OnDisconnecting", "(I)V", instance); DEBUG_ANDROID("Close channels..."); freerdp_channels_disconnect(instance->context->channels, instance); DEBUG_ANDROID("Cleanup threads..."); if (async_channels && channels_thread) { WaitForSingleObject(channels_thread, INFINITE); CloseHandle(channels_thread); } if (async_input && input_thread) { wMessageQueue* input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); if (input_queue) { if (MessageQueue_PostQuit(input_queue, 0)) WaitForSingleObject(input_thread, INFINITE); } CloseHandle(input_thread); } DEBUG_ANDROID("run Disconnecting..."); freerdp_disconnect(instance); freerdp_callback("OnDisconnected", "(I)V", instance); DEBUG_ANDROID("run Quit."); return 0; }
int wlfreerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); freerdp_connect(instance); while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { printf("Failed to get FreeRDP file descriptor"); break; } if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { printf("Failed to get FreeRDP file descriptor"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) { printf("wlfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != TRUE) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE) { printf("Failed to check channel manager file descriptor\n"); break; } } struct display* display; struct window* window; struct wl_context* context; context = (struct wl_context*) instance->context; display = context->display; window = context->window; free(window->buffers[0].shm_data); free(window->buffers[1].shm_data); free(window->data); wl_buffer_destroy(window->buffers[0].buffer); wl_buffer_destroy(window->buffers[1].buffer); wl_shell_surface_destroy(window->shell_surface); wl_surface_destroy(window->surface); wl_shm_destroy(display->shm); wl_shell_destroy(display->shell); wl_compositor_destroy(display->compositor); wl_registry_destroy(display->registry); wl_display_disconnect(display->display); freerdp_channels_close(instance->context->channels, instance); freerdp_channels_free(instance->context->channels); freerdp_free(instance); return 0; }
DWORD WINAPI wf_client_thread(LPVOID lpParam) { MSG msg; int index; int rcount; int wcount; int width; int height; BOOL msg_ret; int quit_msg; void* rfds[32]; void* wfds[32]; int fds_count; HANDLE fds[64]; wfContext* wfc; freerdp* instance; rdpChannels* channels; instance = (freerdp*) lpParam; assert(NULL != instance); wfc = (wfContext*) instance->context; assert(NULL != wfc); ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); if (freerdp_connect(instance) != TRUE) return 0; channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get FreeRDP file descriptor\n"); break; } if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get wfreerdp file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get channel manager file descriptor\n"); break; } fds_count = 0; /* setup read fds */ for (index = 0; index < rcount; index++) { fds[fds_count++] = rfds[index]; } /* setup write fds */ for (index = 0; index < wcount; index++) { fds[fds_count++] = wfds[index]; } /* exit if nothing to do */ if (fds_count == 0) { fprintf(stderr, "wfreerdp_run: fds_count is zero\n"); break; } /* do the wait */ if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) { fprintf(stderr, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X\n", GetLastError()); break; } if (freerdp_check_fds(instance) != TRUE) { fprintf(stderr, "Failed to check FreeRDP file descriptor\n"); break; } if (freerdp_shall_disconnect(instance)) { break; } if (wf_check_fds(instance) != TRUE) { fprintf(stderr, "Failed to check wfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != TRUE) { fprintf(stderr, "Failed to check channel manager file descriptor\n"); break; } wf_process_channel_event(channels, instance); quit_msg = FALSE; while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { msg_ret = GetMessage(&msg, NULL, 0, 0); if (instance->settings->EmbeddedWindow) { if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1)) { PostMessage(wfc->hwnd, WM_SETFOCUS, 0, 0); } else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1)) { PostMessage(wfc->hwnd, WM_KILLFOCUS, 0, 0); } } if (msg.message == WM_SIZE) { width = LOWORD(msg.lParam); height = HIWORD(msg.lParam); //wfc->client_width = width; //wfc->client_height = height; SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); } if ((msg_ret == 0) || (msg_ret == -1)) { quit_msg = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if (quit_msg) break; } /* cleanup */ freerdp_channels_close(channels, instance); freerdp_disconnect(instance); printf("Main thread exited.\n"); ExitThread(0); return 0; }
static gboolean remmina_rdp_main(RemminaProtocolWidget* gp) { gchar* s; gint port; gchar* host; gchar* value; gint rdpsnd_rate; gint rdpsnd_channel; char *rdpsnd_params[3]; int rdpsnd_nparams; char rdpsnd_param1[16]; char rdpsnd_param2[16]; const gchar* cs; RemminaFile* remminafile; rfContext* rfi; gchar *dest_server, *dest_host; gint dest_port; rfi = GET_DATA(gp); remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); s = remmina_plugin_service->protocol_plugin_start_direct_tunnel(gp, 3389, FALSE); if (s == NULL) return FALSE; remmina_plugin_service->get_server_port(s, 3389, &host, &port); rfi->settings->ServerHostname = strdup(host); g_free(host); g_free(s); rfi->settings->ServerPort = port; // Setup rfi->settings->CertificateName when tunneled with SSH if (remmina_plugin_service->file_get_int(remminafile, "ssh_enabled", FALSE)) { dest_server = remmina_plugin_service->file_get_string(remminafile, "server"); if ( dest_server ) { remmina_plugin_service->get_server_port(dest_server, 0, &dest_host, &dest_port); rfi->settings->CertificateName = strdup( dest_host ); g_free(dest_host); } } rfi->settings->ColorDepth = remmina_plugin_service->file_get_int(remminafile, "colordepth", 0); if (rfi->settings->ColorDepth == 0) { rfi->settings->RemoteFxCodec = True; rfi->settings->ColorDepth = 32; } rfi->settings->DesktopWidth = remmina_plugin_service->file_get_int(remminafile, "resolution_width", 1024); rfi->settings->DesktopHeight = remmina_plugin_service->file_get_int(remminafile, "resolution_height", 768); remmina_plugin_service->protocol_plugin_set_width(gp, rfi->settings->DesktopWidth); remmina_plugin_service->protocol_plugin_set_height(gp, rfi->settings->DesktopHeight); if (remmina_plugin_service->file_get_string(remminafile, "username")) rfi->settings->Username = strdup(remmina_plugin_service->file_get_string(remminafile, "username")); if (remmina_plugin_service->file_get_string(remminafile, "domain")) rfi->settings->Domain = strdup(remmina_plugin_service->file_get_string(remminafile, "domain")); THREADS_ENTER s = remmina_plugin_service->file_get_secret(remminafile, "password"); THREADS_LEAVE if (s) { rfi->settings->Password = strdup(s); rfi->settings->AutoLogonEnabled = 1; g_free(s); } if (remmina_plugin_service->file_get_string(remminafile, "clientname")) { s = remmina_plugin_service->file_get_string(remminafile, "clientname"); if ( s ) { free( rfi->settings->ClientHostname ); rfi->settings->ClientHostname = strdup(s); g_free(s); } } else { free( rfi->settings->ClientHostname ); rfi->settings->ClientHostname = strdup( g_get_host_name() ); } if (remmina_plugin_service->file_get_string(remminafile, "exec")) { rfi->settings->AlternateShell = strdup(remmina_plugin_service->file_get_string(remminafile, "exec")); } if (remmina_plugin_service->file_get_string(remminafile, "execpath")) { rfi->settings->ShellWorkingDirectory = strdup(remmina_plugin_service->file_get_string(remminafile, "execpath")); } s = g_strdup_printf("rdp_quality_%i", remmina_plugin_service->file_get_int(remminafile, "quality", DEFAULT_QUALITY_0)); value = remmina_plugin_service->pref_get_value(s); g_free(s); if (value && value[0]) { rfi->settings->PerformanceFlags = strtoul(value, NULL, 16); } else { switch (remmina_plugin_service->file_get_int(remminafile, "quality", DEFAULT_QUALITY_0)) { case 9: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_9; break; case 2: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_2; break; case 1: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_1; break; case 0: default: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_0; break; } } g_free(value); rfi->settings->KeyboardLayout = remmina_rdp_settings_get_keyboard_layout(); if (remmina_plugin_service->file_get_int(remminafile, "console", FALSE)) { rfi->settings->ConsoleSession = True; } cs = remmina_plugin_service->file_get_string(remminafile, "security"); if (g_strcmp0(cs, "rdp") == 0) { rfi->settings->RdpSecurity = True; rfi->settings->TlsSecurity = False; rfi->settings->NlaSecurity = False; } else if (g_strcmp0(cs, "tls") == 0) { rfi->settings->RdpSecurity = False; rfi->settings->TlsSecurity = True; rfi->settings->NlaSecurity = False; } else if (g_strcmp0(cs, "nla") == 0) { rfi->settings->RdpSecurity = False; rfi->settings->TlsSecurity = False; rfi->settings->NlaSecurity = True; } rfi->settings->CompressionEnabled = True; rfi->settings->FastPathInput = True; rfi->settings->FastPathOutput = True; cs = remmina_plugin_service->file_get_string(remminafile, "sound"); if (g_strcmp0(cs, "remote") == 0) { rfi->settings->RemoteConsoleAudio = 1; } else if (g_str_has_prefix(cs, "local")) { rdpsnd_nparams = 0; rdpsnd_params[rdpsnd_nparams++] = "rdpsnd"; cs = strchr(cs, ','); if (cs) { rdpsnd_rate = atoi(cs + 1); if (rdpsnd_rate > 1000 && rdpsnd_rate < 150000) { snprintf( rdpsnd_param1, sizeof(rdpsnd_param1), "rate:%d", rdpsnd_rate ); rdpsnd_params[rdpsnd_nparams++] = rdpsnd_param1; cs = strchr(cs +1, ','); if (cs) { rdpsnd_channel = atoi(cs + 1); if (rdpsnd_channel >= 1 && rdpsnd_channel <= 2) { snprintf( rdpsnd_param2, sizeof(rdpsnd_param2), "channel:%d", rdpsnd_channel ); rdpsnd_params[rdpsnd_nparams++] = rdpsnd_param2; } } } } remmina_rdp_add_static_channel(rfi->settings, rdpsnd_nparams, (char**) rdpsnd_params); } rfi->settings->RedirectClipboard = ( remmina_plugin_service->file_get_int(remminafile, "disableclipboard", FALSE) ? FALSE: TRUE ); cs = remmina_plugin_service->file_get_string(remminafile, "sharefolder"); if (cs && cs[0] == '/') { RDPDR_DRIVE* drive; gsize sz; drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); ZeroMemory(drive, sizeof(RDPDR_DRIVE)); s = strrchr( cs, '/' ); if ( s == NULL || s[1] == 0 ) s = remmina_rdp_plugin_default_drive_name; else s++; s = g_convert_with_fallback(s, -1, "ascii", "utf-8", "_", NULL, &sz, NULL); drive->Type = RDPDR_DTYP_FILESYSTEM; drive->Name = _strdup(s); drive->Path = _strdup(cs); g_free(s); freerdp_device_collection_add(rfi->settings, (RDPDR_DEVICE*) drive); rfi->settings->DeviceRedirection = TRUE; } if (remmina_plugin_service->file_get_int(remminafile, "shareprinter", FALSE)) { RDPDR_PRINTER* printer; printer = (RDPDR_PRINTER*) malloc(sizeof(RDPDR_PRINTER)); ZeroMemory(printer, sizeof(RDPDR_PRINTER)); printer->Type = RDPDR_DTYP_PRINT; freerdp_device_collection_add(rfi->settings, (RDPDR_DEVICE*) printer); rfi->settings->DeviceRedirection = TRUE; } if (remmina_plugin_service->file_get_int(remminafile, "sharesmartcard", FALSE)) { RDPDR_SMARTCARD* smartcard; smartcard = (RDPDR_SMARTCARD*) malloc(sizeof(RDPDR_SMARTCARD)); ZeroMemory(smartcard, sizeof(RDPDR_SMARTCARD)); smartcard->Type = RDPDR_DTYP_SMARTCARD; smartcard->Name = _strdup("scard"); freerdp_device_collection_add(rfi->settings, (RDPDR_DEVICE*) smartcard); rfi->settings->DeviceRedirection = TRUE; } if (!freerdp_connect(rfi->instance)) { if (!rfi->user_cancelled) { remmina_plugin_service->protocol_plugin_set_error(gp, _("Unable to connect to RDP server %s"), rfi->settings->ServerHostname); } return FALSE; } remmina_rdp_main_loop(gp); return TRUE; }
DWORD WINAPI wf_client_thread(LPVOID lpParam) { MSG msg; int width; int height; BOOL msg_ret; int quit_msg; DWORD nCount; HANDLE handles[64]; wfContext* wfc; freerdp* instance; rdpContext* context; rdpChannels* channels; rdpSettings* settings; BOOL async_input; BOOL async_transport; HANDLE input_thread; instance = (freerdp*) lpParam; context = instance->context; wfc = (wfContext*) instance->context; if (!freerdp_connect(instance)) return 0; channels = instance->context->channels; settings = instance->context->settings; async_input = settings->AsyncInput; async_transport = settings->AsyncTransport; if (async_input) { if (!(input_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) wf_input_thread, instance, 0, NULL))) { WLog_ERR(TAG, "Failed to create async input thread."); goto disconnect; } } while (1) { nCount = 0; if (freerdp_focus_required(instance)) { wf_event_focus_in(wfc); wf_event_focus_in(wfc); } if (!async_transport) { DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount); if (tmp == 0) { WLog_ERR(TAG, "freerdp_get_event_handles failed"); break; } nCount += tmp; } if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) { WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X", GetLastError()); break; } if (!async_transport) { if (!freerdp_check_event_handles(context)) { if (wf_auto_reconnect(instance)) continue; WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } } if (freerdp_shall_disconnect(instance)) break; quit_msg = FALSE; while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { msg_ret = GetMessage(&msg, NULL, 0, 0); if (instance->settings->EmbeddedWindow) { if ((msg.message == WM_SETFOCUS) && (msg.lParam == 1)) { PostMessage(wfc->hwnd, WM_SETFOCUS, 0, 0); } else if ((msg.message == WM_KILLFOCUS) && (msg.lParam == 1)) { PostMessage(wfc->hwnd, WM_KILLFOCUS, 0, 0); } } if (msg.message == WM_SIZE) { width = LOWORD(msg.lParam); height = HIWORD(msg.lParam); SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED); } if ((msg_ret == 0) || (msg_ret == -1)) { quit_msg = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if (quit_msg) break; } /* cleanup */ freerdp_channels_disconnect(channels, instance); if (async_input) { wMessageQueue* input_queue; input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE); if (MessageQueue_PostQuit(input_queue, 0)) WaitForSingleObject(input_thread, INFINITE); CloseHandle(input_thread); } disconnect: freerdp_disconnect(instance); WLog_DBG(TAG, "Main thread exited."); ExitThread(0); return 0; }
int android_freerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; int select_status; struct timeval timeout; assert(instance); memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (!freerdp_connect(instance)) { freerdp_callback("OnConnectionFailure", "(I)V", instance); return 0; } ((androidContext*)instance->context)->is_connected = TRUE; while (!freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get channel manager file descriptor\n"); break; } if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { DEBUG_ANDROID("Failed to get android file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; timeout.tv_sec = 1; timeout.tv_usec = 0; select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout); if (select_status == 0) continue; else if (select_status == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { DEBUG_ANDROID("android_run: select failed\n"); break; } } if (freerdp_shall_disconnect(instance)) break; if (freerdp_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n"); break; } if (android_check_fds(instance) != TRUE) { DEBUG_ANDROID("Failed to check android file descriptor\n"); break; } if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE) { DEBUG_ANDROID("Failed to check channel manager file descriptor\n"); break; } android_process_channel_event(instance->context->channels, instance); } // issue another OnDisconnecting here in case the disconnect was initiated by the sever and not our client freerdp_callback("OnDisconnecting", "(I)V", instance); freerdp_channels_close(instance->context->channels, instance); freerdp_disconnect(instance); gdi_free(instance); cache_free(instance->context->cache); android_cliprdr_uninit(instance); freerdp_callback("OnDisconnected", "(I)V", instance); return 0; }
static gboolean remmina_rdp_main(RemminaProtocolWidget* gp) { gchar* s; gint port; gchar* host; gchar* value; gint rdpdr_num; gint drdynvc_num; gint rdpsnd_num; const gchar* cs; RemminaFile* remminafile; rfContext* rfi; rfi = GET_DATA(gp); remminafile = remmina_plugin_service->protocol_plugin_get_file(gp); s = remmina_plugin_service->protocol_plugin_start_direct_tunnel(gp, 3389, FALSE); if (s == NULL) return FALSE; remmina_plugin_service->get_server_port(s, 3389, &host, &port); rfi->settings->ServerHostname = strdup(host); g_free(host); g_free(s); rfi->settings->ServerPort = port; rfi->settings->ColorDepth = remmina_plugin_service->file_get_int(remminafile, "colordepth", 0); if (rfi->settings->ColorDepth == 0) { rfi->settings->RemoteFxCodec = True; rfi->settings->ColorDepth = 32; } rfi->settings->DesktopWidth = remmina_plugin_service->file_get_int(remminafile, "resolution_width", 1024); rfi->settings->DesktopHeight = remmina_plugin_service->file_get_int(remminafile, "resolution_height", 768); remmina_plugin_service->protocol_plugin_set_width(gp, rfi->settings->DesktopWidth); remmina_plugin_service->protocol_plugin_set_height(gp, rfi->settings->DesktopHeight); if (remmina_plugin_service->file_get_string(remminafile, "username")) rfi->settings->Username = strdup(remmina_plugin_service->file_get_string(remminafile, "username")); if (remmina_plugin_service->file_get_string(remminafile, "domain")) rfi->settings->Domain = strdup(remmina_plugin_service->file_get_string(remminafile, "domain")); THREADS_ENTER s = remmina_plugin_service->file_get_secret(remminafile, "password"); THREADS_LEAVE if (s) { rfi->settings->Password = strdup(s); rfi->settings->AutoLogonEnabled = 1; g_free(s); } if (remmina_plugin_service->file_get_string(remminafile, "clientname")) { strncpy(rfi->settings->ClientHostname, remmina_plugin_service->file_get_string(remminafile, "clientname"), sizeof(rfi->settings->ClientHostname) - 1); } else { strncpy(rfi->settings->ClientHostname, g_get_host_name(), sizeof(rfi->settings->ClientHostname) - 1); } if (remmina_plugin_service->file_get_string(remminafile, "exec")) { rfi->settings->AlternateShell = strdup(remmina_plugin_service->file_get_string(remminafile, "exec")); } if (remmina_plugin_service->file_get_string(remminafile, "execpath")) { rfi->settings->ShellWorkingDirectory = strdup(remmina_plugin_service->file_get_string(remminafile, "execpath")); } s = g_strdup_printf("rdp_quality_%i", remmina_plugin_service->file_get_int(remminafile, "quality", DEFAULT_QUALITY_0)); value = remmina_plugin_service->pref_get_value(s); g_free(s); if (value && value[0]) { rfi->settings->PerformanceFlags = strtoul(value, NULL, 16); } else { switch (remmina_plugin_service->file_get_int(remminafile, "quality", DEFAULT_QUALITY_0)) { case 9: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_9; break; case 2: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_2; break; case 1: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_1; break; case 0: default: rfi->settings->PerformanceFlags = DEFAULT_QUALITY_0; break; } } g_free(value); rfi->settings->KeyboardLayout = remmina_rdp_settings_get_keyboard_layout(); if (remmina_plugin_service->file_get_int(remminafile, "console", FALSE)) { rfi->settings->ConsoleSession = True; } cs = remmina_plugin_service->file_get_string(remminafile, "security"); if (g_strcmp0(cs, "rdp") == 0) { rfi->settings->RdpSecurity = True; rfi->settings->TlsSecurity = False; rfi->settings->NlaSecurity = False; } else if (g_strcmp0(cs, "tls") == 0) { rfi->settings->RdpSecurity = False; rfi->settings->TlsSecurity = True; rfi->settings->NlaSecurity = False; } else if (g_strcmp0(cs, "nla") == 0) { rfi->settings->RdpSecurity = False; rfi->settings->TlsSecurity = False; rfi->settings->NlaSecurity = True; } rfi->settings->CompressionEnabled = True; rfi->settings->FastPathInput = True; rfi->settings->FastPathOutput = True; drdynvc_num = 0; rdpsnd_num = 0; cs = remmina_plugin_service->file_get_string(remminafile, "sound"); if (g_strcmp0(cs, "remote") == 0) { rfi->settings->RemoteConsoleAudio = 1; } else if (g_str_has_prefix(cs, "local")) { cs = strchr(cs, ','); if (cs) { snprintf(rfi->rdpsnd_options, sizeof(rfi->rdpsnd_options), "%s", cs + 1); s = strchr(rfi->rdpsnd_options, ','); if (s) *s++ = '\0'; rfi->rdpsnd_data[rdpsnd_num].size = sizeof(RDP_PLUGIN_DATA); rfi->rdpsnd_data[rdpsnd_num].data[0] = "rate"; rfi->rdpsnd_data[rdpsnd_num].data[1] = rfi->rdpsnd_options; rdpsnd_num++; if (s) { rfi->rdpsnd_data[rdpsnd_num].size = sizeof(RDP_PLUGIN_DATA); rfi->rdpsnd_data[rdpsnd_num].data[0] = "channel"; rfi->rdpsnd_data[rdpsnd_num].data[1] = s; rdpsnd_num++; } } remmina_rdp_load_plugin(rfi->channels, rfi->settings, "rdpsnd", rfi->rdpsnd_data); rfi->drdynvc_data[drdynvc_num].size = sizeof(RDP_PLUGIN_DATA); rfi->drdynvc_data[drdynvc_num].data[0] = "audin"; drdynvc_num++; } if (drdynvc_num) { remmina_rdp_load_plugin(rfi->channels, rfi->settings, "drdynvc", rfi->drdynvc_data); } if (!remmina_plugin_service->file_get_int(remminafile, "disableclipboard", FALSE)) { remmina_rdp_load_plugin(rfi->channels, rfi->settings, "cliprdr", NULL); } rdpdr_num = 0; cs = remmina_plugin_service->file_get_string(remminafile, "sharefolder"); if (cs && cs[0] == '/') { s = strrchr (cs, '/'); s = (s && s[1] ? s + 1 : "root"); rfi->rdpdr_data[rdpdr_num].size = sizeof(RDP_PLUGIN_DATA); rfi->rdpdr_data[rdpdr_num].data[0] = "disk"; rfi->rdpdr_data[rdpdr_num].data[1] = s; rfi->rdpdr_data[rdpdr_num].data[2] = (gchar*) cs; rdpdr_num++; } if (remmina_plugin_service->file_get_int(remminafile, "shareprinter", FALSE)) { rfi->rdpdr_data[rdpdr_num].size = sizeof(RDP_PLUGIN_DATA); rfi->rdpdr_data[rdpdr_num].data[0] = "printer"; rdpdr_num++; } if (remmina_plugin_service->file_get_int(remminafile, "sharesmartcard", FALSE)) { rfi->rdpdr_data[rdpdr_num].size = sizeof(RDP_PLUGIN_DATA); rfi->rdpdr_data[rdpdr_num].data[0] = "scard"; rfi->rdpdr_data[rdpdr_num].data[1] = "scard"; rdpdr_num++; } if (rdpdr_num) { remmina_rdp_load_plugin(rfi->channels, rfi->settings, "rdpdr", rfi->rdpdr_data); } if (!freerdp_connect(rfi->instance)) { if (!rfi->user_cancelled) { remmina_plugin_service->protocol_plugin_set_error(gp, _("Unable to connect to RDP server %s"), rfi->settings->ServerHostname); } return FALSE; } remmina_rdp_main_loop(gp); return TRUE; }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; if (p_demux->out == NULL) return VLC_EGENERIC; p_sys = vlc_obj_calloc( p_this, 1, sizeof(demux_sys_t) ); if( !p_sys ) return VLC_ENOMEM; p_sys->f_fps = var_InheritFloat( p_demux, CFG_PREFIX "fps" ); if ( p_sys->f_fps <= 0 ) p_sys->f_fps = 1.0; p_sys->i_frame_interval = CLOCK_FREQ / p_sys->f_fps; #if FREERDP_VERSION_MAJOR == 1 && FREERDP_VERSION_MINOR < 2 freerdp_channels_global_init(); #endif p_sys->p_instance = freerdp_new(); if ( !p_sys->p_instance ) { msg_Err( p_demux, "rdp instantiation error" ); return VLC_EGENERIC; } p_demux->p_sys = p_sys; p_sys->p_instance->PreConnect = preConnectHandler; p_sys->p_instance->PostConnect = postConnectHandler; p_sys->p_instance->Authenticate = authenticateHandler; /* Set up context handlers and let it be allocated */ p_sys->p_instance->ContextSize = sizeof( vlcrdp_context_t ); freerdp_context_new( p_sys->p_instance ); vlcrdp_context_t * p_vlccontext = (vlcrdp_context_t *) p_sys->p_instance->context; p_vlccontext->p_demux = p_demux; /* Parse uri params for pre-connect */ vlc_url_t url; vlc_UrlParse( &url, p_demux->psz_location ); if ( !EMPTY_STR(url.psz_host) ) p_sys->psz_hostname = strdup( url.psz_host ); else p_sys->psz_hostname = strdup( "localhost" ); p_sys->i_port = ( url.i_port > 0 ) ? url.i_port : 3389; vlc_UrlClean( &url ); if ( ! freerdp_connect( p_sys->p_instance ) ) { msg_Err( p_demux, "can't connect to rdp server" ); goto error; } if ( vlc_clone( &p_sys->thread, DemuxThread, p_demux, VLC_THREAD_PRIORITY_INPUT ) != VLC_SUCCESS ) { msg_Err( p_demux, "can't spawn thread" ); freerdp_disconnect( p_sys->p_instance ); goto error; } p_demux->pf_demux = NULL; p_demux->pf_control = Control; return VLC_SUCCESS; error: freerdp_free( p_sys->p_instance ); free( p_sys->psz_hostname ); return VLC_EGENERIC; }
int guac_client_init(guac_client* client, int argc, char** argv) { rdp_guac_client_data* guac_client_data; guac_rdp_settings* settings; freerdp* rdp_inst; /* Validate number of arguments received */ if (argc != RDP_ARGS_COUNT) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Wrong argument count received."); return 1; } /* Allocate client data */ guac_client_data = malloc(sizeof(rdp_guac_client_data)); /* Init random number generator */ srandom(time(NULL)); /* Init client */ #ifdef HAVE_FREERDP_CHANNELS_GLOBAL_INIT freerdp_channels_global_init(); #endif rdp_inst = freerdp_new(); rdp_inst->PreConnect = rdp_freerdp_pre_connect; rdp_inst->PostConnect = rdp_freerdp_post_connect; rdp_inst->Authenticate = rdp_freerdp_authenticate; rdp_inst->VerifyCertificate = rdp_freerdp_verify_certificate; rdp_inst->ReceiveChannelData = __guac_receive_channel_data; /* Allocate FreeRDP context */ #ifdef LEGACY_FREERDP rdp_inst->context_size = sizeof(rdp_freerdp_context); #else rdp_inst->ContextSize = sizeof(rdp_freerdp_context); #endif rdp_inst->ContextNew = (pContextNew) rdp_freerdp_context_new; rdp_inst->ContextFree = (pContextFree) rdp_freerdp_context_free; freerdp_context_new(rdp_inst); /* Set settings */ settings = &(guac_client_data->settings); /* Console */ settings->console = (strcmp(argv[IDX_CONSOLE], "true") == 0); settings->console_audio = (strcmp(argv[IDX_CONSOLE_AUDIO], "true") == 0); /* Certificate and auth */ settings->ignore_certificate = (strcmp(argv[IDX_IGNORE_CERT], "true") == 0); settings->disable_authentication = (strcmp(argv[IDX_DISABLE_AUTH], "true") == 0); /* NLA security */ if (strcmp(argv[IDX_SECURITY], "nla") == 0) { guac_client_log(client, GUAC_LOG_INFO, "Security mode: NLA"); settings->security_mode = GUAC_SECURITY_NLA; } /* TLS security */ else if (strcmp(argv[IDX_SECURITY], "tls") == 0) { guac_client_log(client, GUAC_LOG_INFO, "Security mode: TLS"); settings->security_mode = GUAC_SECURITY_TLS; } /* RDP security */ else if (strcmp(argv[IDX_SECURITY], "rdp") == 0) { guac_client_log(client, GUAC_LOG_INFO, "Security mode: RDP"); settings->security_mode = GUAC_SECURITY_RDP; } /* ANY security (allow server to choose) */ else if (strcmp(argv[IDX_SECURITY], "any") == 0) { guac_client_log(client, GUAC_LOG_INFO, "Security mode: ANY"); settings->security_mode = GUAC_SECURITY_ANY; } /* If nothing given, default to RDP */ else { guac_client_log(client, GUAC_LOG_INFO, "No security mode specified. Defaulting to RDP."); settings->security_mode = GUAC_SECURITY_RDP; } /* Set hostname */ settings->hostname = strdup(argv[IDX_HOSTNAME]); /* If port specified, use it */ settings->port = RDP_DEFAULT_PORT; if (argv[IDX_PORT][0] != '\0') settings->port = atoi(argv[IDX_PORT]); guac_client_log(client, GUAC_LOG_DEBUG, "Client resolution is %ix%i at %i DPI", client->info.optimal_width, client->info.optimal_height, client->info.optimal_resolution); /* Use suggested resolution unless overridden */ settings->resolution = guac_rdp_suggest_resolution(client); if (argv[IDX_DPI][0] != '\0') settings->resolution = atoi(argv[IDX_DPI]); /* Use optimal width unless overridden */ settings->width = client->info.optimal_width * settings->resolution / client->info.optimal_resolution; 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(client, GUAC_LOG_ERROR, "Invalid width: \"%s\". Using default of %i.", argv[IDX_WIDTH], settings->width); } /* Round width down to nearest multiple of 4 */ settings->width = settings->width & ~0x3; /* Use optimal height unless overridden */ settings->height = client->info.optimal_height * settings->resolution / client->info.optimal_resolution; 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(client, GUAC_LOG_ERROR, "Invalid height: \"%s\". Using default of %i.", argv[IDX_WIDTH], settings->height); } guac_client_log(client, GUAC_LOG_DEBUG, "Using resolution of %ix%i at %i DPI", settings->width, settings->height, settings->resolution); /* Domain */ settings->domain = NULL; if (argv[IDX_DOMAIN][0] != '\0') settings->domain = strdup(argv[IDX_DOMAIN]); /* Username */ settings->username = NULL; if (argv[IDX_USERNAME][0] != '\0') settings->username = strdup(argv[IDX_USERNAME]); /* Password */ settings->password = NULL; if (argv[IDX_PASSWORD][0] != '\0') settings->password = strdup(argv[IDX_PASSWORD]); /* Client name */ settings->client_name = NULL; if (argv[IDX_CLIENT_NAME][0] != '\0') settings->client_name = strdup(argv[IDX_CLIENT_NAME]); /* Initial program */ settings->initial_program = NULL; if (argv[IDX_INITIAL_PROGRAM][0] != '\0') settings->initial_program = strdup(argv[IDX_INITIAL_PROGRAM]); /* RemoteApp program */ settings->remote_app = NULL; if (argv[IDX_REMOTE_APP][0] != '\0') settings->remote_app = strdup(argv[IDX_REMOTE_APP]); /* RemoteApp working directory */ settings->remote_app_dir = NULL; if (argv[IDX_REMOTE_APP_DIR][0] != '\0') settings->remote_app_dir = strdup(argv[IDX_REMOTE_APP_DIR]); /* RemoteApp arguments */ settings->remote_app_args = NULL; if (argv[IDX_REMOTE_APP_ARGS][0] != '\0') settings->remote_app_args = strdup(argv[IDX_REMOTE_APP_ARGS]); /* Static virtual channels */ settings->svc_names = NULL; if (argv[IDX_STATIC_CHANNELS][0] != '\0') settings->svc_names = guac_split(argv[IDX_STATIC_CHANNELS], ','); /* Performance flags */ settings->wallpaper_enabled = (strcmp(argv[IDX_ENABLE_WALLPAPER], "true") == 0); settings->theming_enabled = (strcmp(argv[IDX_ENABLE_THEMING], "true") == 0); settings->font_smoothing_enabled = (strcmp(argv[IDX_ENABLE_FONT_SMOOTHING], "true") == 0); settings->full_window_drag_enabled = (strcmp(argv[IDX_ENABLE_FULL_WINDOW_DRAG], "true") == 0); settings->desktop_composition_enabled = (strcmp(argv[IDX_ENABLE_DESKTOP_COMPOSITION], "true") == 0); settings->menu_animations_enabled = (strcmp(argv[IDX_ENABLE_MENU_ANIMATIONS], "true") == 0); /* 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(client, GUAC_LOG_ERROR, "Invalid color-depth: \"%s\". Using default of %i.", argv[IDX_WIDTH], settings->color_depth); } /* Audio enable/disable */ guac_client_data->settings.audio_enabled = (strcmp(argv[IDX_DISABLE_AUDIO], "true") != 0); /* Printing enable/disable */ guac_client_data->settings.printing_enabled = (strcmp(argv[IDX_ENABLE_PRINTING], "true") == 0); /* Drive enable/disable */ guac_client_data->settings.drive_enabled = (strcmp(argv[IDX_ENABLE_DRIVE], "true") == 0); guac_client_data->settings.drive_path = strdup(argv[IDX_DRIVE_PATH]); guac_client_data->settings.create_drive_path = (strcmp(argv[IDX_CREATE_DRIVE_PATH], "true") == 0); /* Store client data */ guac_client_data->rdp_inst = rdp_inst; guac_client_data->mouse_button_mask = 0; guac_client_data->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); guac_client_data->requested_clipboard_format = CB_FORMAT_TEXT; guac_client_data->audio = NULL; guac_client_data->filesystem = NULL; guac_client_data->available_svc = guac_common_list_alloc(); /* 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 */ settings->server_layout = NULL; if (argv[IDX_SERVER_LAYOUT][0] != '\0') settings->server_layout = guac_rdp_keymap_find(argv[IDX_SERVER_LAYOUT]); /* If no keymap requested, use default */ if (settings->server_layout == NULL) settings->server_layout = guac_rdp_keymap_find(GUAC_DEFAULT_KEYMAP); /* Load keymap into client */ __guac_rdp_client_load_keymap(client, settings->server_layout); #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."); /* Parse username - use RDP username by default */ const char* sftp_username = argv[IDX_SFTP_USERNAME]; if (sftp_username[0] == '\0' && settings->username != NULL) sftp_username = settings->username; guac_client_data->sftp_user = guac_common_ssh_create_user(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."); /* Parse password - use RDP password by default */ const char* sftp_password = argv[IDX_SFTP_PASSWORD]; if (sftp_password[0] == '\0' && settings->password != NULL) sftp_password = settings->password; guac_common_ssh_user_set_password(guac_client_data->sftp_user, sftp_password); } /* Parse hostname - use RDP hostname by default */ const char* sftp_hostname = argv[IDX_SFTP_HOSTNAME]; if (sftp_hostname[0] == '\0') sftp_hostname = settings->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') { client->file_handler = guac_rdp_sftp_file_handler; guac_common_ssh_sftp_set_upload_path( guac_client_data->sftp_filesystem, argv[IDX_SFTP_DIRECTORY]); } /* Otherwise, use SFTP for basic uploads only if drive not enabled */ else if (!settings->drive_enabled) client->file_handler = guac_rdp_sftp_file_handler; guac_client_log(client, GUAC_LOG_DEBUG, "SFTP connection succeeded."); } #endif /* Create default surface */ guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, settings->width, settings->height); guac_client_data->current_surface = guac_client_data->default_surface; /* Send connection name */ guac_protocol_send_name(client->socket, settings->hostname); /* Set default pointer */ guac_common_set_pointer_cursor(client); /* Push desired settings to FreeRDP */ guac_rdp_push_settings(settings, rdp_inst); /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Error connecting to RDP server"); return 1; } /* Success */ return 0; }
int dfreerdp_run(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; dfInfo* dfi; dfContext* context; rdpChannels* channels; ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); if (!freerdp_connect(instance)) return 0; context = (dfContext*) instance->context; dfi = context->dfi; channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get FreeRDP file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get channel manager file descriptor\n"); break; } if (df_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) { fprintf(stderr, "Failed to get dfreerdp file descriptor\n"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { fprintf(stderr, "dfreerdp_run: select failed\n"); break; } } if (freerdp_check_fds(instance) != TRUE) { fprintf(stderr, "Failed to check FreeRDP file descriptor\n"); break; } if (df_check_fds(instance, &rfds_set) != TRUE) { fprintf(stderr, "Failed to check dfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != TRUE) { fprintf(stderr, "Failed to check channel manager file descriptor\n"); break; } df_process_channel_event(channels, instance); } freerdp_channels_close(channels, instance); freerdp_channels_free(channels); df_free(dfi); gdi_free(instance); freerdp_disconnect(instance); freerdp_free(instance); return 0; }
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; }
int wfreerdp_run(freerdp* instance) { MSG msg; int index; int rcount; int wcount; BOOL msg_ret; int quit_msg; void* rfds[32]; void* wfds[32]; int fds_count; HANDLE fds[64]; rdpChannels* channels; memset(rfds, 0, sizeof(rfds)); memset(wfds, 0, sizeof(wfds)); if (freerdp_connect(instance) != true) return 0; channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get wfreerdp file descriptor\n"); break; } if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true) { printf("Failed to get channel manager file descriptor\n"); break; } fds_count = 0; /* setup read fds */ for (index = 0; index < rcount; index++) { fds[fds_count++] = rfds[index]; } /* setup write fds */ for (index = 0; index < wcount; index++) { fds[fds_count++] = wfds[index]; } /* exit if nothing to do */ if (fds_count == 0) { printf("wfreerdp_run: fds_count is zero\n"); break; } /* do the wait */ if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1, QS_ALLINPUT) == WAIT_FAILED) { printf("wfreerdp_run: WaitForMultipleObjects failed: 0x%04X\n", GetLastError()); break; } if (freerdp_check_fds(instance) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } if (wf_check_fds(instance) != true) { printf("Failed to check wfreerdp file descriptor\n"); break; } if (freerdp_channels_check_fds(channels, instance) != true) { printf("Failed to check channel manager file descriptor\n"); break; } wf_process_channel_event(channels, instance); quit_msg = FALSE; while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { msg_ret = GetMessage(&msg, NULL, 0, 0); if (msg_ret == 0 || msg_ret == -1) { quit_msg = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if (quit_msg) break; } /* cleanup */ freerdp_channels_free(channels); freerdp_free(instance); return 0; }
void* tf_client_thread_proc(freerdp* instance) { int i; int fds; int max_fds; int rcount; int wcount; void* rfds[32]; void* wfds[32]; fd_set rfds_set; fd_set wfds_set; rdpChannels* channels; channels = instance->context->channels; freerdp_connect(instance); while (1) { rcount = 0; wcount = 0; ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); break; } if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get channel manager file descriptor"); break; } max_fds = 0; FD_ZERO(&rfds_set); FD_ZERO(&wfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { WLog_ERR(TAG, "tfreerdp_run: select failed"); break; } } if (!freerdp_check_fds(instance)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } if (!freerdp_channels_check_fds(channels, instance)) { WLog_ERR(TAG, "Failed to check channel manager file descriptor"); break; } } freerdp_channels_close(channels, instance); freerdp_channels_free(channels); freerdp_free(instance); ExitThread(0); return NULL; }