/** * Send a plugin-defined event to the plugin. * called only from main thread * @param channels the channel manager instance * @param event an event object created by freerdp_event_new() */ FREERDP_API int freerdp_channels_send_event(rdpChannels* chan_man, RDP_EVENT* event) { struct channel_data* lchan_data; int index; const char* name; name = event_class_to_name_table[event->event_class]; if (name == NULL) { DEBUG_CHANNELS("unknown event_class %d", event->event_class); freerdp_event_free(event); return 1; } lchan_data = freerdp_channels_find_channel_data_by_name(chan_man, name, &index); if (lchan_data == NULL) { DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } if (lchan_data->open_event_proc != NULL) { lchan_data->open_event_proc(lchan_data->open_handle, CHANNEL_EVENT_USER, event, sizeof(RDP_EVENT), sizeof(RDP_EVENT), 0); } return 0; }
/** * Send a plugin-defined event to the plugin. * called only from main thread * @param channels the channel manager instance * @param event an event object created by freerdp_event_new() */ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* event) { int index; const char* name = NULL; rdpChannelData* lchannel_data; switch (GetMessageClass(event->id)) { case DebugChannel_Class: name = "rdpdbg"; break; case CliprdrChannel_Class: name = "cliprdr"; break; case TsmfChannel_Class: name = "tsmf"; break; case RailChannel_Class: name = "rail"; break; } if (!name) { DEBUG_CHANNELS("unknown event_class %d", event->event_class); freerdp_event_free(event); return 1; } lchannel_data = freerdp_channels_find_channel_data_by_name(channels, name, &index); if (!lchannel_data) { DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } if (lchannel_data->open_event_proc) { lchannel_data->open_event_proc(lchannel_data->open_handle, CHANNEL_EVENT_USER, event, sizeof(wMessage), sizeof(wMessage), 0); } return 0; }
/** * Send a plugin-defined event to the plugin. * called only from main thread * @param channels the channel manager instance * @param event an event object created by freerdp_event_new() */ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* event) { const char* name = NULL; CHANNEL_OPEN_DATA* pChannelOpenData; switch (GetMessageClass(event->id)) { case DebugChannel_Class: name = "rdpdbg"; break; case CliprdrChannel_Class: name = "cliprdr"; break; case TsmfChannel_Class: name = "tsmf"; break; case RailChannel_Class: name = "rail"; break; } if (!name) { DEBUG_CHANNELS("unknown event_class %d", GetMessageClass(event->id)); freerdp_event_free(event); return 1; } pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name); if (!pChannelOpenData) { DEBUG_CHANNELS("could not find channel name %s", name); freerdp_event_free(event); return 1; } if (pChannelOpenData->pChannelOpenEventProc) { pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, CHANNEL_EVENT_USER, event, sizeof(wMessage), sizeof(wMessage), 0); } return 0; }
//----------------------------------------------------------------------------- static void process_events_and_channel_data_from_plugin(thread_param* param) { RDP_EVENT* event; param->th_count++; while (param->th_to_finish == 0) { freerdp_channels_check_fds(param->chan_man, param->instance); while (1) { event = freerdp_channels_pop_event(param->chan_man); if (event == NULL) break; static int counter = 0; counter++; printf("UI receive event. (type=%d counter=%d).\n", event->event_type, counter); // add to global event list if (param->in_events_number < RAIL_ARRAY_SIZE(param->in_events)) { save_event(event, ¶m->in_events[param->in_events_number]); param->in_events_number++; } freerdp_event_free(event); } usleep(1000); } param->th_count--; }
void rds_process_channel_event(rdpChannels* channels, freerdp* instance) { rdsContext* rds; wMessage* event; rds = (rdsContext*) instance->context; event = freerdp_channels_pop_event(channels); if (event) { switch (GetMessageClass(event->id)) { case RailChannel_Class: break; case TsmfChannel_Class: break; case CliprdrChannel_Class: break; case RdpeiChannel_Class: break; default: break; } freerdp_event_free(event); } }
void test_channels(void) { rdpChannels* chan_man; rdpSettings settings = { 0 }; freerdp instance = { 0 }; RDP_EVENT* event; settings.hostname = "testhost"; instance.settings = &settings; instance.SendChannelData = test_rdp_channel_data; chan_man = freerdp_channels_new(); freerdp_channels_load_plugin(chan_man, &settings, "../channels/rdpdbg/rdpdbg.so", NULL); freerdp_channels_pre_connect(chan_man, &instance); freerdp_channels_post_connect(chan_man, &instance); freerdp_channels_data(&instance, 0, "testdata", 8, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 8); freerdp_channels_data(&instance, 0, "testdata1", 9, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 9); freerdp_channels_data(&instance, 0, "testdata11", 10, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 10); freerdp_channels_data(&instance, 0, "testdata111", 11, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, 11); event = freerdp_event_new(RDP_EVENT_CLASS_DEBUG, 0, NULL, NULL); freerdp_channels_send_event(chan_man, event); while ((event = freerdp_channels_pop_event(chan_man)) == NULL) { freerdp_channels_check_fds(chan_man, &instance); } printf("responded event_type %d\n", event->event_type); freerdp_event_free(event); freerdp_channels_close(chan_man, &instance); freerdp_channels_free(chan_man); }
static void cliprdr_process_event(rdpSvcPlugin* plugin, wMessage* event) { switch (GetMessageType(event->id)) { case CliprdrChannel_FormatList: cliprdr_process_format_list_event((cliprdrPlugin*) plugin, (RDP_CB_FORMAT_LIST_EVENT*) event); break; case CliprdrChannel_DataRequest: cliprdr_process_format_data_request_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_REQUEST_EVENT*) event); break; case CliprdrChannel_DataResponse: cliprdr_process_format_data_response_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; case CliprdrChannel_FilecontentsRequest: cliprdr_process_filecontents_request_event((cliprdrPlugin*) plugin, (RDP_CB_FILECONTENTS_REQUEST_EVENT*) event); break; case CliprdrChannel_FilecontentsResponse: cliprdr_process_filecontents_response_event((cliprdrPlugin*) plugin, (RDP_CB_FILECONTENTS_RESPONSE_EVENT*) event); break; case CliprdrChannel_LockClipdata: cliprdr_process_lock_clipdata_event((cliprdrPlugin*) plugin, (RDP_CB_LOCK_CLIPDATA_EVENT*) event); break; case CliprdrChannel_UnLockClipdata: cliprdr_process_unlock_clipdata_event((cliprdrPlugin*) plugin, (RDP_CB_UNLOCK_CLIPDATA_EVENT*) event); break; case CliprdrChannel_TemporaryDirectory: cliprdr_process_tempdir_event((cliprdrPlugin*) plugin, (RDP_CB_TEMPDIR_EVENT*) event); break; default: WLog_ERR(TAG, "unknown event type %d", GetMessageType(event->id)); break; } freerdp_event_free(event); }
static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation) { RDP_REDRAW_EVENT* revent; if (presentation->last_width && presentation->last_height) { revent = (RDP_REDRAW_EVENT*) freerdp_event_new(TsmfChannel_Class, TsmfChannel_Redraw, NULL, NULL); revent->x = presentation->last_x; revent->y = presentation->last_y; revent->width = presentation->last_width; revent->height = presentation->last_height; if (!tsmf_push_event(presentation->channel_callback, (wMessage*) revent)) { freerdp_event_free((wMessage*) revent); } presentation->last_x = 0; presentation->last_y = 0; presentation->last_width = 0; presentation->last_height = 0; } }
static void rdpdbg_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event) { DEBUG_WARN("event_type %d", event->event_type); freerdp_event_free(event); event = freerdp_event_new(FRDP_EVENT_CLASS_DEBUG, 0, NULL, NULL); svc_plugin_send_event(plugin, event); }
static void sample_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { printf("sample_process_event:\n"); /* events coming from main freerdp window to plugin */ /* send them back with svc_plugin_send_event */ freerdp_event_free(event); }
static void sample_process_event(rdpSvcPlugin* plugin, wMessage* event) { fprintf(stderr, "sample_process_event:\n"); /* events coming from main freerdp window to plugin */ /* send them back with svc_plugin_send_event */ freerdp_event_free(event); }
void wf_process_channel_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; event = freerdp_channels_pop_event(channels); if (event) freerdp_event_free(event); }
static void svc_data_in_item_free(svc_data_in_item* item) { if (item->data_in) { stream_free(item->data_in); item->data_in = NULL; } if (item->event_in) { freerdp_event_free(item->event_in); item->event_in = NULL; } xfree(item); }
static void rail_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { railPlugin* rail = NULL; rail = (railPlugin*) plugin; switch (event->event_type) { case RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS: rail_recv_set_sysparams_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP: rail_recv_exec_remote_app_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE: rail_recv_activate_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU: rail_recv_sysmenu_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND: rail_recv_syscommand_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT: rail_recv_notify_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE: rail_recv_window_move_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ: rail_recv_app_req_event(rail->rail_order, event); break; case RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO: rail_recv_langbarinfo_event(rail->rail_order, event); break; default: break; } freerdp_event_free(event); }
static void rail_process_event(rdpSvcPlugin* plugin, wMessage* event) { railPlugin* rail = NULL; rail = (railPlugin*) plugin; switch (GetMessageType(event->id)) { case RailChannel_ClientSystemParam: rail_recv_set_sysparams_event(rail->rail_order, event); break; case RailChannel_ClientExecute: rail_recv_exec_remote_app_event(rail->rail_order, event); break; case RailChannel_ClientActivate: rail_recv_activate_event(rail->rail_order, event); break; case RailChannel_ClientSystemMenu: rail_recv_sysmenu_event(rail->rail_order, event); break; case RailChannel_ClientSystemCommand: rail_recv_syscommand_event(rail->rail_order, event); break; case RailChannel_ClientNotifyEvent: rail_recv_notify_event(rail->rail_order, event); break; case RailChannel_ClientWindowMove: rail_recv_window_move_event(rail->rail_order, event); break; case RailChannel_ClientGetAppIdRequest: rail_recv_app_req_event(rail->rail_order, event); break; case RailChannel_ClientLanguageBarInfo: rail_recv_langbarinfo_event(rail->rail_order, event); break; default: break; } freerdp_event_free(event); }
void tf_process_channel_event(rdpChanMan* chanman, freerdp* instance) { RDP_EVENT* event; event = freerdp_chanman_pop_event(chanman); if (event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_SYNC: tf_process_cb_sync_event(chanman, instance); break; default: printf("tf_process_channel_event: unknown event type %d\n", event->event_type); break; } freerdp_event_free(event); } }
void android_process_channel_event(rdpChannels* channels, freerdp* instance) { wMessage* event; event = freerdp_channels_pop_event(channels); if (event) { switch(GetMessageClass(event->id)) { case CliprdrChannel_Class: android_process_cliprdr_event(instance, event); break; default: break; } freerdp_event_free(event); } }
void tf_process_channel_event(rdpChannels* channels, freerdp* instance) { RDP_EVENT* event; event = freerdp_channels_pop_event(channels); if (event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_MONITOR_READY: tf_process_cb_monitor_ready_event(channels, instance); break; default: printf("tf_process_channel_event: unknown event type %d\n", event->event_type); break; } freerdp_event_free(event); } }
static void cliprdr_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event) { switch (event->event_type) { case FRDP_EVENT_TYPE_CB_FORMAT_LIST: cliprdr_process_format_list_event((cliprdrPlugin*)plugin, (FRDP_CB_FORMAT_LIST_EVENT*)event); break; case FRDP_EVENT_TYPE_CB_DATA_REQUEST: cliprdr_process_format_data_request_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_REQUEST_EVENT*)event); break; case FRDP_EVENT_TYPE_CB_DATA_RESPONSE: cliprdr_process_format_data_response_event((cliprdrPlugin*)plugin, (FRDP_CB_DATA_RESPONSE_EVENT*)event); break; default: DEBUG_WARN("unknown event type %d", event->event_type); break; } freerdp_event_free(event); }
void tf_process_channel_event(rdpChannels* channels, freerdp* instance) { wMessage* event; event = freerdp_channels_pop_event(channels); if (event) { switch (GetMessageType(event->id)) { case CliprdrChannel_MonitorReady: tf_process_cb_monitor_ready_event(channels, instance); break; default: printf("tf_process_channel_event: unknown event type %d\n", GetMessageType(event->id)); break; } freerdp_event_free(event); } }
//----------------------------------------------------------------------------- static void process_events_and_channel_data_from_plugin(thread_param* param) { FRDP_EVENT* event; param->th_count++; while (param->th_to_finish == 0) { freerdp_chanman_check_fds(param->chan_man, param->instance); event = freerdp_chanman_pop_event(param->chan_man); if (event) { DEBUG_RAIL("UI receive %d event.", event->event_type); debug_event(event); // add to global event list freerdp_event_free(event); } usleep(1000); } param->th_count--; }
static void tsmf_presentation_restore_last_video_frame(TSMF_PRESENTATION* presentation) { RDP_REDRAW_EVENT* revent; if (presentation->last_width && presentation->last_height) { revent = (RDP_REDRAW_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_TSMF, RDP_EVENT_TYPE_TSMF_REDRAW, NULL, NULL); revent->x = presentation->last_x; revent->y = presentation->last_y; revent->width = presentation->last_width; revent->height = presentation->last_height; if (!tsmf_push_event(presentation->channel_callback, (RDP_EVENT*) revent)) { freerdp_event_free((RDP_EVENT*) revent); } presentation->last_x = 0; presentation->last_y = 0; presentation->last_width = 0; presentation->last_height = 0; } }
void wf_process_channel_event(rdpChannels* channels, freerdp* instance) { wfContext* wfc; wMessage* event; wfc = (wfContext*) instance->context; event = freerdp_channels_pop_event(channels); if (event) { switch (GetMessageClass(event->id)) { case CliprdrChannel_Class: wf_process_cliprdr_event(wfc, event); break; default: break; } freerdp_event_free(event); } }
static void android_process_channel_event(rdpChannels* channels, freerdp* instance) { wMessage* event; event = freerdp_channels_pop_event(channels); if (event) { int ev = GetMessageClass(event->id); switch(ev) { case CliprdrChannel_Class: android_process_cliprdr_event(instance, event); break; default: DEBUG_ANDROID("Unsupported channel event %08X", ev); break; } freerdp_event_free(event); } }
static void cliprdr_process_event(rdpSvcPlugin* plugin, wMessage* event) { switch (GetMessageType(event->id)) { case CliprdrChannel_FormatList: cliprdr_process_format_list_event((cliprdrPlugin*) plugin, (RDP_CB_FORMAT_LIST_EVENT*) event); break; case CliprdrChannel_DataRequest: cliprdr_process_format_data_request_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_REQUEST_EVENT*) event); break; case CliprdrChannel_DataResponse: cliprdr_process_format_data_response_event((cliprdrPlugin*) plugin, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; default: DEBUG_WARN("unknown event type %d", GetMessageType(event->id)); break; } freerdp_event_free(event); }
void guac_rdpsnd_process_event(rdpSvcPlugin* plugin, wMessage* event) { freerdp_event_free(event); }
static void rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) { freerdp_event_free(event); }
static void drdynvc_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event) { freerdp_event_free(event); }
void test_cliprdr(void) { int i; rdpChannels* channels; rdpSettings settings = { 0 }; freerdp instance = { 0 }; RDP_EVENT* event; RDP_CB_FORMAT_LIST_EVENT* format_list_event; RDP_CB_DATA_REQUEST_EVENT* data_request_event; RDP_CB_DATA_RESPONSE_EVENT* data_response_event; settings.hostname = "testhost"; instance.settings = &settings; instance.SendChannelData = test_rdp_channel_data; channels = freerdp_channels_new(); freerdp_channels_load_plugin(channels, &settings, "../channels/cliprdr/cliprdr.so", NULL); freerdp_channels_pre_connect(channels, &instance); freerdp_channels_post_connect(channels, &instance); /* server sends cliprdr capabilities and monitor ready PDU */ freerdp_channels_data(&instance, 0, (char*)test_clip_caps_data, sizeof(test_clip_caps_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_clip_caps_data) - 1); freerdp_channels_data(&instance, 0, (char*)test_monitor_ready_data, sizeof(test_monitor_ready_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_monitor_ready_data) - 1); /* cliprdr sends clipboard_sync event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_MONITOR_READY); freerdp_event_free(event); /* UI sends format_list event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, event_process_callback, NULL); format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; format_list_event->num_formats = 2; format_list_event->formats = (uint32*) xmalloc(sizeof(uint32) * 2); format_list_event->formats[0] = CB_FORMAT_TEXT; format_list_event->formats[1] = CB_FORMAT_HTML; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends format list PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* server sends format list response PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_format_list_response_data, sizeof(test_format_list_response_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_response_data) - 1); /* server sends format list PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_format_list_data, sizeof(test_format_list_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_format_list_data) - 1); /* cliprdr sends format_list event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_FORMAT_LIST); if (event->event_type == RDP_EVENT_TYPE_CB_FORMAT_LIST) { format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; for (i = 0; i < format_list_event->num_formats; i++) printf("Format: 0x%X\n", format_list_event->formats[i]); } freerdp_event_free(event); /* server sends data request PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_data_request_data, sizeof(test_data_request_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_request_data) - 1); /* cliprdr sends data request event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_DATA_REQUEST); if (event->event_type == RDP_EVENT_TYPE_CB_DATA_REQUEST) { data_request_event = (RDP_CB_DATA_REQUEST_EVENT*)event; printf("Requested format: 0x%X\n", data_request_event->format); } freerdp_event_free(event); /* UI sends data response event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_RESPONSE, event_process_callback, NULL); data_response_event = (RDP_CB_DATA_RESPONSE_EVENT*)event; data_response_event->data = (uint8*)xmalloc(6); strcpy((char*)data_response_event->data, "hello"); data_response_event->size = 6; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends data response PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* UI sends data request event to cliprdr */ event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_DATA_REQUEST, event_process_callback, NULL); data_request_event = (RDP_CB_DATA_REQUEST_EVENT*)event; data_request_event->format = CB_FORMAT_UNICODETEXT; event_processed = 0; freerdp_channels_send_event(channels, event); /* cliprdr sends data request PDU to server */ while (!event_processed) { freerdp_channels_check_fds(channels, &instance); } /* server sends data response PDU to cliprdr */ freerdp_channels_data(&instance, 0, (char*)test_data_response_data, sizeof(test_data_response_data) - 1, CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, sizeof(test_data_response_data) - 1); /* cliprdr sends data response event to UI */ while ((event = freerdp_channels_pop_event(channels)) == NULL) { freerdp_channels_check_fds(channels, &instance); } printf("Got event %d\n", event->event_type); CU_ASSERT(event->event_type == RDP_EVENT_TYPE_CB_DATA_RESPONSE); if (event->event_type == RDP_EVENT_TYPE_CB_DATA_RESPONSE) { data_response_event = (RDP_CB_DATA_RESPONSE_EVENT*)event; printf("Data response size: %d\n", data_response_event->size); freerdp_hexdump(data_response_event->data, data_response_event->size); } freerdp_event_free(event); freerdp_channels_close(channels, &instance); freerdp_channels_free(channels); }
/** * 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; }