DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count) { DWORD nCount = 0; nCount += transport_get_event_handles(context->rdp->transport, events, count); if (nCount == 0) return 0; if (events && (nCount < count + 2)) { events[nCount++] = freerdp_channels_get_event_handle(context->instance); events[nCount++] = getChannelErrorEventHandle(context); events[nCount++] = context->abortEvent; } else return 0; if (context->settings->AsyncInput) { if (nCount >= count) return 0; events[nCount++] = freerdp_get_message_queue_event_handle( context->instance, FREERDP_INPUT_MESSAGE_QUEUE); } return nCount; }
static void* jni_input_thread(void* arg) { HANDLE event[3]; wMessageQueue* queue; freerdp* instance = (freerdp*) arg; androidContext *aCtx = (androidContext*)instance->context; assert(NULL != instance); assert(NULL != aCtx); DEBUG_ANDROID("input_thread Start."); if (!(queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE))) goto fail_get_message_queue; if (!(event[0] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, aCtx->event_queue->pipe_fd[0], WINPR_FD_READ))) goto fail_create_event_0; if (!(event[1] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, aCtx->event_queue->pipe_fd[1], WINPR_FD_READ))) goto fail_create_event_1; if (!(event[2] = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE))) goto fail_get_message_queue_event; do { DWORD rc = WaitForMultipleObjects(3, event, FALSE, INFINITE); if ((rc < WAIT_OBJECT_0) || (rc > WAIT_OBJECT_0 + 2)) continue; if (rc == WAIT_OBJECT_0 + 2) { wMessage msg; MessageQueue_Peek(queue, &msg, FALSE); if (msg.id == WMQ_QUIT) break; } if (android_check_fds(instance) != TRUE) break; } while(1); DEBUG_ANDROID("input_thread Quit."); fail_get_message_queue_event: CloseHandle(event[1]); fail_create_event_1: CloseHandle(event[0]); fail_create_event_0: MessageQueue_PostQuit(queue, 0); fail_get_message_queue: ExitThread(0); return NULL; }
static void* jni_input_thread(void* arg) { HANDLE event[2]; wMessageQueue* queue; freerdp* instance = (freerdp*) arg; WLog_DBG(TAG, "input_thread Start."); if (!(queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE))) goto disconnect; if (!(event[0] = android_get_handle(instance))) goto disconnect; if (!(event[1] = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE))) goto disconnect; do { DWORD rc = WaitForMultipleObjects(2, event, FALSE, INFINITE); if ((rc < WAIT_OBJECT_0) || (rc > WAIT_OBJECT_0 + 1)) continue; if (rc == WAIT_OBJECT_0 + 1) { wMessage msg; MessageQueue_Peek(queue, &msg, FALSE); if (msg.id == WMQ_QUIT) break; } if (android_check_handle(instance) != TRUE) break; } while (1); WLog_DBG(TAG, "input_thread Quit."); disconnect: MessageQueue_PostQuit(queue, 0); ExitThread(0); return NULL; }
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; }